2

I create a NSNumberFormatter as below, set the max fraction digits to 2, and when I tried to format @"93.650000", it output like 93.65000000000001. I am confused, what's wrong with it?

Edit: My problem is, I don't what to output 93.65000000000001 as string, just 93.65 as string.

NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
f.minimumFractionDigits = 0;
f.maximumFractionDigits = 2;
NSString *valueString;
for (NSString *valueStr in valueStrArray) {
    valueString = valueStr;
    if ((NSNull *)valueString == [NSNull null])
        valueString = @"0";
    NSNumber *value = [f numberFromString:valueString];
    [vArray addObject:value];
}

original value string array:

<__NSCFArray 0x1742e8700>(
95.370000,
93.650000,
76.330000,
73.040000,
70.050000,
69,
66.510000,
57.540000,
53.760000,
<null>
)

formatted NSNumber array: (lldb) po vArray

<__NSArrayM 0x174c524b0>(
95.37,
93.65000000000001,
76.33,
73.04000000000001,
70.05,
69,
66.51000000000001,
57.54,
53.76,
0
)
Wingzero
  • 9,644
  • 10
  • 39
  • 80
  • This I is a limitation of the internal NSNumber type which will be 32bit of 64bit floating point. It tries to store the value the best as it can, but not having infinite bits, has to round it to the closest bit representative that it can. Thats why its not recommended to use doubles or floats for, forloop variables – Barnstokkr Mar 23 '15 at 07:47
  • Then How can I solve it? – Wingzero Mar 23 '15 at 07:48
  • @Wingzero You haven't presented the actual problem. You have been told *why* you are getting the `000000000001` at the end, but what is wrong with that? You can simply ignore it. – trojanfoe Mar 23 '15 at 07:49
  • @trojanfoe I have edited my problem. I don't care what it stores like, but when I tried to print this 93.65000000000001 as string, I just want 93.65. But it gives me @"93.65000000000001" – Wingzero Mar 23 '15 at 07:51
  • Use `[NSString stringWithFormat:@"%.2f", [numberObject floatValue]]` to format it. Better still use the `NSNumberFormatter` object you created. – trojanfoe Mar 23 '15 at 07:53
  • http://stackoverflow.com/questions/9540301/how-to-print-formatted-float-in-obj-c – Barnstokkr Mar 23 '15 at 07:53
  • Holy xxx... I just forgot this solution – Wingzero Mar 23 '15 at 07:53
  • @trojanfoe please post your answer and I will accept it. – Wingzero Mar 23 '15 at 07:55
  • FWIW: setting multiplier of the formatter to nil fixes this issue on iOS 12. It has not been possible for me to verify neither the reason for the bug, nor why setting multipler=nil fixes it (even if it is already nil). – Kasper Munck Dec 03 '18 at 14:19

2 Answers2

1

You could try NSDecimalNumber instead of NSNumber for a better handling of decimal numbers. It has a class method +decimalNumberWithString:

Thyraz
  • 2,412
  • 2
  • 21
  • 23
0

@Barnstokkr (in the comments) has explained that this is a floating-point rounding error and if the issue is that the number contains the additional 000000000001 at the end when formatted, then simply use the NSNumberFormatter object to format the string, or [NSString stringWithFormat:]:

NSString *formatted = [f stringFromNumber:numberObj];
NSString *formatted = [NSString stringWithFormat:@"%.2f", [numberObj floatValue]];
trojanfoe
  • 120,358
  • 21
  • 212
  • 242