15

Can somebody explain why multiplying by 100 here gives a less accurate result but multiplying by 10 twice gives a more accurate result?

± % sc
Loading development environment (Rails 3.0.1)
>> 129.95 * 100
12994.999999999998
>> 129.95*10
1299.5
>> 129.95*10*10
12995.0
4
  • 1
    Most likely due to binary representation of floating point numbers. You can't write extactly 129.95 in base 2 I assume. Commented Oct 29, 2010 at 20:28
  • 10
    Obligatory Link: What Every Computer Scientist Should Know About Floating-Point Arithmetic Commented Oct 29, 2010 at 21:00
  • Any clues at to why this would NOT be happening for me? I'm trying to demonstrate this, and I enter 129.95 * 100 as above into IRB and I unexpectedly get the correct answer. Commented Nov 12, 2013 at 4:57
  • To answer my own question - seems Float#to_s rounds. Doing this works: printf("%.50f", 129.95 * 100) Commented Nov 12, 2013 at 5:05

3 Answers 3

29

If you do the calculations by hand in double-precision binary, which is limited to 53 significant bits, you'll see what's going on:

129.95 = 1.0000001111100110011001100110011001100110011001100110 x 2^7

129.95*100 = 1.1001011000010111111111111111111111111111111111111111011 x 2^13

This is 56 significant bits long, so rounded to 53 bits it's

1.1001011000010111111111111111111111111111111111111111 x 2^13, which equals

12994.999999999998181010596454143524169921875

Now 129.95*10 = 1.01000100110111111111111111111111111111111111111111111 x 2^10

This is 54 significant bits long, so rounded to 53 bits it's 1.01000100111 x 2^10 = 1299.5

Now 1299.5 * 10 = 1.1001011000011 x 2^13 = 12995.

Sign up to request clarification or add additional context in comments.

Comments

4

First off: you are looking at the string representation of the result, not the actual result itself. If you really want to compare the two results, you should format both results explicitly, using String#% and you should format both results the same way.

Secondly, that's just how binary floating point numbers work. They are inexact, they are finite and they are binary. All three mean that you get rounding errors, which generally look totally random, unless you happen to have memorized the entirety of IEEE754 and can recite it backwards in your sleep.

Comments

3

There is no floating point number exactly equal to 129.95. So your language uses a value which is close to it instead. When that value is multiplied by 100, the result is close to 12995, but it just so happens to not equal 12995. (It is also not exactly equal to 100 times the original value it used in place of 129.95.) So your interpreter prints a decimal number which is close to (but not equal to) the value of 129.95 * 100 and which shows you that it is not exactly 12995. It also just so happens that the result 129.95 * 10 is exactly equal to 1299.5. This is mostly luck.

Bottom line is, never expect equality out of any floating point arithmetic, only "closeness".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.