NSDecimalNumber and large unsigned long long (64-bit) integers

后端 未结 2 560
野趣味
野趣味 2021-02-19 08:11

I\'m handling large 64 bit unsigned integers from a JSON source which are being parsed into NSDecimalNumbers, which is apparently to \"faithfully represent arbitrary-precision n

相关标签:
2条回答
  • 2021-02-19 08:52

    I've had a response from Apple on this issue via the developer forums:

    This is a standing issue with NSDecimalNumber where the simple accessors (such as [unsigned]longLongValue) go through the doubleValue accessor – this any value requiring more than 53 bits of precision will be inappropriately rounded. Feel free to Report a Bug about this issue and mention bug number 8220543.

    That said, if you are just getting 64-bit numbers from JSON, you should be able to just use NSNumber instead of NSDecimalNumber.

    So I'm solving it by changing parser from SBJson to JSONKit, which is not only much faster, it also maps numbers into NSNumber objects instead of NSDecimalNumber objects.

    0 讨论(0)
  • 2021-02-19 09:14

    If you still want to extract an unsigned long long value from an NSDecimalNumber, you could use the approach suggested by johne here and do something like the following:

    NSDecimalNumber *testNumber = [NSDecimalNumber decimalNumberWithString:@"18446744073709551615"];
    unsigned long long ullvalue = strtoull([[testNumber stringValue] UTF8String], NULL, 0);
    NSLog(@"Number:%llu", ullvalue);
    

    which produces the proper result of

    Number:18446744073709551615

    I tried to do this using an NSScanner:

    NSScanner *theScanner = [[NSScanner alloc] initWithString:[testNumber stringValue]];
    unsigned long long outputValue;
    
    [theScanner scanLongLong:(long long *)&outputValue];
    [theScanner release];
    

    but unfortunately, it only reads the signed long long values, so the above gives the incorrect value of 9223372036854775807.

    0 讨论(0)
提交回复
热议问题