Search code examples
objective-cnsstringnsnumberformatter

doubleValue from NSString, decimals get removed


Here I am using NSNumberFormater to set max number of decimals in a double to two. It seems to work fine, but when I try to convert it back to a double, from the string generated by NSNumberFormater, as you can see in the NSLog output, any decimal is removed and replaced by trailing zeros. Why is this?

- (double)randomDoubleBetween:(double)smallNumber and:(double)bigNumber {
    double diff = bigNumber - smallNumber;
    double ranNum = (((double) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * diff) + smallNumber;

    NSNumberFormatter *doubleValueWithMaxDecimalDigits = [[NSNumberFormatter alloc] init];
    [doubleValueWithMaxDecimalDigits setNumberStyle:NSNumberFormatterDecimalStyle];
    [doubleValueWithMaxDecimalDigits setMaximumFractionDigits:2];
    NSNumber *num = [NSNumber numberWithDouble:ranNum];

    NSString *valueToReturn = [doubleValueWithMaxDecimalDigits stringFromNumber:num];
    NSLog(@"String value %@", valueToReturn);

    NSLog(@"Double value converted from string %f", [valueToReturn doubleValue]);
    return [valueToReturn doubleValue];
}

NSLog output:

2013-08-09 02:25:05.031 GG[27947:907] String value 176,19

2013-08-09 02:25:05.035 GG[27947:907] Double value converted from string 176.000000


Solution

  • Looks like -[NSString doubleValue] isn't respecting the locale decimal separator; it expects a point, not a comma.

    // US uses point as decimal separator
    [doubleValueWithMaxDecimalDigits setLocale:[[NSLocale alloc]initWithLocaleIdentifier:@"en_US"]];
    
    NSString *valueToReturn = [doubleValueWithMaxDecimalDigits stringFromNumber:num];
    
    // Correctly includes fractional part
    NSLog(@"Double value converted from string %lf", [valueToReturn doubleValue]);
    
    // Italy uses a comma
    [doubleValueWithMaxDecimalDigits setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"it_IT"]];
    valueToReturn = [doubleValueWithMaxDecimalDigits stringFromNumber:num];
    
    // Drops fractional part
    NSLog(@"Double value converted from string %lf", [valueToReturn doubleValue]);
    

    I'm not sure why you're formatting the number into a string that you don't use, but if you're going to continue to do that, use the same formatter again to parse the string into a double before returning.

    (Aside, your format specifier is wrong; use %lf for double.)