2012-02-09 4 views
7

일부 숫자 비교를 시도하고 있는데 이상한 결과가 나타납니다.NSNumber 비교 : 다른 결과 반환

NSNumber* number1 = [NSNumber numberWithFloat:1.004]; 
NSNumber* number2 = [NSNumber numberWithDouble:1.004]; 

([number1 compare:number2] == NSOrderedSame) ? NSLog(@"YES") : NSLog(@"NO"); 
([number1 compare:number2] == NSOrderedAscending) ? NSLog(@"YES") : NSLog(@"NO"); 
([number1 doubleValue] == [number2 doubleValue]) ? NSLog(@"YES") : NSLog(@"NO"); 
([number1 floatValue] == [number2 floatValue]) ? NSLog(@"YES") : NSLog(@"NO"); 

로그 출력 :

NO
YES
NO
YES

이 나에게 매우 실망. 아마 float의 비트 수와 double의 비트 수의 차이 때문일 것입니다. 그것은 내게 그것은 double을 float로 잘라서 비교하는 것으로 보인다. 그러나 번호가 어떻게 생성되는지 모르면 올바른 결과를 얻으려면 어떻게해야합니까? NSNumber를 비교하는 다른 방법이 있습니까?

+3

당신이 사용하는 경우에 대한'[번호 1 isEqualToNumber : 숫자 2] ', 그것은 선호되는 방법입니다. 적어도 가치 평등을 확인하려는 경우에만 그렇습니까? – twilson

+1

죄송 twilson, 여전히 NO를 반환합니다. 번호는 다릅니다. – picciano

답변

7

내가 isEqualToNumber:를 사용하여 시도하고 NO 반환을 제공합니다. 그들이 동일하지 않은 이유는 1.004가 정확하게 이진수로 표현 될 수 없기 때문입니다. double 근사치는 float 근사치보다 소수점 이하로 더 많은 자리가 있으므로 두 숫자가 다릅니다.

NSNumber* number1 = [NSNumber numberWithFloat:1.004]; 
NSNumber* number2 = [NSNumber numberWithDouble:1.004]; 

NSLog(@"number 1: %.12f", [number1 doubleValue]); 
NSLog(@"number 2: %.12f", [number2 doubleValue]); 

([number1 isEqualToNumber:number2]) ? NSLog(@"YES") : NSLog(@"NO"); 
fabs([number1 floatValue] - [number2 doubleValue]) < 1.0e-7 ? NSLog(@"YES") : NSLog(@"NO"); 

결과 : 부동 소수점 숫자를 비교할 때 일반적으로, 당신은 그들이 허용 오차 값 fabs(a - b) < tolerance 내에서 동일한 있는지 확인하기 위해 테스트

2012-02-09 15:08:34.272 so9219935[3313:903] number 1: 1.003999948502 
2012-02-09 15:08:34.274 so9219935[3313:903] number 2: 1.004000000000 
2012-02-09 15:08:34.275 so9219935[3313:903] NO 
2012-02-09 15:08:34.275 so9219935[3313:903] YES 
+0

아주 좋은 해결책! Apple이 compare : 메소드를 사용하여이 문제를 처리하지 않는다는 사실에 나에게 미친 듯이 보입니다. –

+5

Apple (또는 더 정확하게 컴파일러 작성자)은 프로그래머의 평등성에 대한 가정을 가정 할 수 없습니다. 그들이 할 수있는 일은 프로그래머가 정확히 말한 것입니다. 이 경우 두 개의 부동 한 값을 비교했습니다.부동 소수점 숫자는 사소한 주제가 아닙니다. 시간이 있으면 [모든 컴퓨터 과학자가 부동 소수점 연산에 대해 알아야 할 내용] (http://www-users.math.umd.edu/~jkolesar/mait613/floating_point_math.pdf)을 살펴보십시오. – SSteve

+0

참조 해 주셔서 감사합니다. 나는 이것에 대한 권장되는 읽기를 찾고 있었다. 나는이 문제에 대해 잠시 알고 있었으며 그것에 대해 아무 것도하지 않았다. :) –

2

compare : 메소드는 유형 변환을위한 표준 C 규칙을 따릅니다. 예를 들어 정수 값을 가진 NSNumber 개체와 부동 소수점 값이있는 NSNumber 개체를 비교하면 정수 값이 비교를 위해 부동 소수점 값으로 변환됩니다.

또한 NSNumber를 부동 소수점으로 초기화 한 다음 이중으로 변환하면 정밀도가 떨어집니다. 당신은 플로트와 복식의 혼합이있을 수 있습니다 알고있는 경우

NSNumber* number1 = [NSNumber numberWithFloat:1.004]; 
NSNumber* number2 = [NSNumber numberWithDouble:1.004]; 
NSLog(@"number1 double: %1.16f", [number1 doubleValue]); 
NSLog(@"number2 double: %1.16f", [number2 doubleValue]); 
NSLog(@"number1 objCType %s", [number1 objCType]); 
NSLog(@"number2 objCType %s", [number2 objCType]); 

2012-02-09 15:59:49.487 testNSNumber[89283:f803] number1 double: 1.0039999485015869 
2012-02-09 15:59:49.488 testNSNumber[89283:f803] number2 double: 1.0040000000000000 
2012-02-09 16:21:01.655 testNSNumber[4351:f803] number1 objCType f 
2012-02-09 16:21:01.656 testNSNumber[4351:f803] number2 objCType d 

는, 하나 개의 솔루션은 귀하의 질문에 코드의 마지막 줄에서했던 것처럼의 NSNumber의 floatValues를 비교하는 것입니다.

또한 objCType 메서드를 사용하여 NSNumber의 데이터 형식을 가져올 수 있습니다.

+0

정말 그 objType을 좋아합니다! 고맙습니다! –

2

isEqualToNumber 시도하십시오 : 당신의 상태

([number1 isEqualToNumber:number2]) ? NSLog(@"YES") : NSLog(@"NO"); 

this stackoverflow question을 확인하는 방법도 상세한 답변을

+0

예상대로 작동하지 않으며 "NO"가 기록됩니다. float 및 double로 초기화 된 NSNumber는 다른 값입니다. 위의 내 대답을 참조하십시오. 참조 할 수있는 질문은 모든 수레를 사용하는 것입니다. – picciano