1

Possible Duplicate:
Trouble with floats in Objective-C

I have broken this problem down to about as simple as i can get it. Feel free to try the same thing and tell me if you get the same error and what solution you might have. I have already tried it on several computers.

float total = 200000.0f + 154196.8f;
NSLog(@"total: %f", total);

The output is:

total: 354196.812500

If anyone has any sort of logical explanation, feel free to share it.

Community
  • 1
  • 1
Kris Gellci
  • 9,539
  • 6
  • 40
  • 47
  • 3
    Why tag with `xcode` which is unrelated to Xcode? –  Dec 19 '12 at 15:14
  • Xcode is the environment I'm using when this occurs. Try not to change peoples posts next time. – Kris Gellci Dec 19 '12 at 15:15
  • 3
    no. The implementation, at best, is OS X and GCC/clang (whichever). The issue would be the same of you used another IDE. –  Dec 19 '12 at 15:16
  • What's interesting is that if you change it to a double instead of a float, the issue disappears. `double total = 200000.0 + 154196.8; NSLog(@"total: %f", total);` – CBredlow Dec 19 '12 at 15:18
  • 3
    This is nothing to do with Objective-C or the environment - it's just the way floating point math works. – John Parker Dec 19 '12 at 15:19
  • 4
    @KrisGellci The "edit" function over 2000 rep is there for a reason. Try not to be agressive and ignorant next time. –  Dec 19 '12 at 15:19
  • I guess ill just convert over to double as stated below. – Kris Gellci Dec 19 '12 at 15:30
  • Converting to double will reduce, but not eliminate, these issues. If you have enough leading digits you will still see rounding error. It will just be moved out from about the 7th or 8th significant digit to the 15th or 16th. 0.8 is not exactly representable in any binary floating point format. – Patricia Shanahan Dec 19 '12 at 17:09
  • I just need accuracy to about the second or third decimal place, making some computations with dollar amounts. Switching to doubles seems to be working fine for this case. – Kris Gellci Dec 20 '12 at 19:38

3 Answers3

13

I'd suggest you brush up on your floats

http://www.altdevblogaday.com/2012/05/20/thats-not-normalthe-performance-of-odd-floats/

If you need higher precision use a double.

Additionally http://randomascii.wordpress.com/2012/03/08/float-precisionfrom-zero-to-100-digits-2/

Nico
  • 3,826
  • 1
  • 21
  • 31
  • Double works, i know that there are inaccuracies with floating point, i was just surprised that i couldn't do a simple .80 + .00 – Kris Gellci Dec 19 '12 at 15:22
7

See What Every Programmer Should Know About Floating-Point Arithmetic for all the deep understanding. The short answer is that all floating point representations have limitations on their precision, and that things that can be expressed in a small number of digits in decimal may not be expressible in a small number of digits in binary (and specifically not in floating point formats).

Note that while double can improve things, it is no panacea. It is quite common to have small rounding errors, even with double. You may easily get 1.99999999 when you expect 2.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
3

Hint:

long double total = 200000.0 + 154196.8;
NSLog(@"total: %Lf", total);

On my machine prints the correct value.
A 32 bit floating point has a 23 bit mantissa, the closest value is 0.5+0.25+0.125.
You should use more bits to get the correct representation.

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
  • More bits will get *closer* but even a 10,000 bit binary floating-point number cannot represent .8. That is the crux of the problem. You can't represent 4/5 in binary floating-point because the denominator is, necessarily, always a power of two. It's like trying to represent 1/3 exactly as a base-ten decimal. 0.3333 converges, but never arrives. – Bruce Dawson Apr 16 '14 at 16:15