Reputation: 860
Here is code:
NSNumber* number = [NSDecimalNumber decimalNumberWithString :@"11111111111111111"];
NSLog(@"%@ = %lld", number, [number unsignedLongLongValue]);
And I get output:
11111111111111111 = 11111111111111112
Is it known bug or I do something wrong?
UPDATE: bug reported: https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/3/wo/Stnn5Aaocknzx52c64zbN0/5.83.28.0.9
Upvotes: 0
Views: 750
Reputation: 170319
I believe the issue is that you are using NSNumber's -longLongValue
method on an NSDecimalNumber. NSDecimalNumber stores a high-precision representation of the number internally as a decimal, but NSNumber just keeps it as an IEEE 754 double precision floating-point value. If I recall correctly, if you use the standard NSNumber superclass methods on an NSDecimalNumber, the internal number is first converted to a double, which can introduce binary floating-point artifacts like this.
As neoneye suggests, a way around this might be to use an NSString as an intermediary. For example:
NSDecimalNumber* number = [NSDecimalNumber decimalNumberWithString :@"11111111111111111"];
double number2 = [@"11111111111111111" doubleValue];
NSLog(@"%@ = %lld = %f", number, [[number descriptionWithLocale:nil] longLongValue], number2);
Will produce the result 11111111111111111 = 11111111111111111 = 11111111111111112.000000
, showing both the correct result from the decimal number extraction and the error that happens when this number is temporarily stored in a double.
Upvotes: 2