1

I'm using xcode. I have something like this in my code

NSNumber *a=[NSNumber numberWithDouble:[@"0.07" doubleValue]];
//after that line a value is  0.07000000000000001

NSNumber *a=[NSNumber numberWithDouble:[@"0.099999999999999" doubleValue]];

// after that line a value is 0.09999999999999901

I found these 2 exceptions. Others numbers are working fine. How can I fix it?

i need to convert a string in a nsnumber, but this is trowing my a wrong number i need a value to be 0.07 equal as the string number. This number will be typed by the user and i need to show later the number exactly how he typed it, i cant rounding it with a formatter, because i don't know the quantity of decimals that the user type.

KGS-12
  • 537
  • 4
  • 7
  • Also, I think the Python tutorial has a great explanation of what's going on here: http://docs.python.org/release/2.6/tutorial/floatingpoint.html – jscs May 31 '13 at 19:06
  • I think @HotLicks has the right duplicate. It's also worth noting that the various comparison and arithmetic operators will still work as if those extra decimal places were not present. For example, if you evaluate (0.07==0.070000000000000001) in Xcode's lldb debugger you'll get back "true." – Aaron Golden May 31 '13 at 19:20
  • @HotLicks why would any reasonable float => decimal conversion represent the value 0.07 represents as 0.070000000000001 ? – John Dvorak May 31 '13 at 20:47
  • 1
    @JanDvorak: There's no decimal conversion here. `NSNumber` is just an object wrapper for primitive numbers; it stores values in their original form. – jscs May 31 '13 at 20:49
  • @JoshCaswell the debugger has to the conversion, then. – John Dvorak May 31 '13 at 20:50
  • @JanDvorak Oh, I see what you mean. The debugger (or `NSLog()`) just truncate; they can't possibly know how many digits are actually significant without being told explicitly. – jscs May 31 '13 at 20:52
  • @JanDvorak: Because the number that the value 0.07 represents in IEEE-754 floating point is roughly 0.070000000000001. – Chuck May 31 '13 at 20:54
  • @JoshCaswell the conversion _should_ truncate as much as possible without altering the value. Javascript's `toString` does exactly that. Ruby's `to_s` behaves well for `0.07` too. – John Dvorak May 31 '13 at 20:56
  • Altering _which_ value, @JanDvorak? The code doing the printing has no idea about what value the programmer wrote down, and the value that's stored actually _is_ `0.0700000000001something`. – jscs May 31 '13 at 21:18
  • @JoshCaswell the conversion should truncate as much as possible while preserving the fact that the closest representable value to the output representation is the one being represented. `0.07` represents the value represented by `0.07` just fine. – John Dvorak May 31 '13 at 21:22
  • 1
    @JanDvorak: But it does not represent the value represented by 0.0700000000001 just fine — and it's the *same value*. – Chuck May 31 '13 at 21:26
  • @Chuck well, it does. 0.0700000000001 might be closer to the real value than 0.07, but the real value is as close to 0.07 as you can get. Thus, 0.07 represents that value just fine. 0.0700000000001 represents the same value slightly better, but it's kinda wasteful when 0.07 represents _that_ value as well. – John Dvorak May 31 '13 at 21:30
  • 1
    @JanDvorak: I don't follow. You're suggesting that if I type 0.070000000000144, that should be printed as "0.07"? How is that any more reasonable? – Chuck May 31 '13 at 21:35
  • @Chuck it is reasonable since `0.070000000000144 == 0.07` (the Double data type is not just good enough to pick up the difference) and `0.07` is the shorter of them two. If they were different, then how did the latter turn into the former? Then the duplicates are incorrect. – John Dvorak May 31 '13 at 21:40
  • Indeed, `0.070000000000000001 == 0.07` and the debugger / IDE got this one wrong (or "wrong"). – John Dvorak May 31 '13 at 21:42
  • this number is entry by the user so i can't change it. And also i need to use nsnumber to do some operations, and then show the user the number typed. that's why i need exactly the same number. – KGS-12 May 31 '13 at 21:48
  • @Chuck please check your zeroes. Copy-pasted from the question, they are equal and `0.07` represents `0.070000000000000001` just fine. Copy-pasted from your comment, they are _not_ equal, and `0.070000000000144` should not be rounded. `0.07000000000000000144` should. `0.0700000000000000144` may be rounded to `0.07000000000000002`. Also, `0.07000000000000003 == 0.07000000000000004`. – John Dvorak May 31 '13 at 21:49
  • @user2441567 they are exactly the same. It's just the debugger that displays more digits than it needs to. – John Dvorak May 31 '13 at 21:49
  • the number coopy-pasted is 0.07000000000000001 – KGS-12 May 31 '13 at 21:55
  • i get the answer... Floating-point numbers are inherently imprecise. If you need to redisplay exactly what the user typed, you should store the user's text as a string. – KGS-12 May 31 '13 at 22:36

0 Answers0