Why does Visual Studio 2008 tell me .9 - .8999999999999995 = 0.00000000000000055511151231257827?
Asked Answered
B

6

8

When I type this into the Visual Studio 2008 immediate window:

? .9 - .8999999999999995

It gives me this as the answer:

0.00000000000000055511151231257827

The documentation says that a double has 15-16 digits of precision, but it's giving me a result with 32 digits of precision. Where is all that extra precision coming from?

Burget answered 2/11, 2009 at 17:30 Comment(7)
I wonder how many questions related to floating point precision problems we have on SO.Braziel
@Mehrdad: Way too many. It's such a simple thing: base 10 != base 2. Yet, everyone feels compelled to treat it like it's the Most Amazing Thing Ever!Inclination
People, please read, this is about why the answer uses 32 digits. Not about not being exact.Aphasic
Henk, please comprehend, that's not how floating point works.Chicken
Henk, I think this question could have been phrased better. If OP had even mentioned in the beginning of the question that he/she knew about FP precision, then it probably would have stopped all of the FP answers.Binomial
@Mehrdad's comment makes me wonder how many distinct floating point precision problems are possible.Stander
@Mehrdad: I write a script to count it, and there are 201.00000001918371 such questions. not sure how I counted a fractional question though, maybe I'll post a question with my source code to ask for an explanation.Egocentric
H
41

There are only 15-16 digits in the answer. All those leading zeroes don't count. The number is actually more like 5.5511151231257827 × 10-16. The mantissa portion has 15-16 digits in it. The exponent (-16) serves to shift the decimal point over by 16 places, but doesn't change the number of digits in the overall number.

Edit

After getting some comments, I'm curious now about what's really going on. I plugged the number in question into this IEEE-754 Converter. It took the liberty of rounding the last "27" into "30", but I don't think that changes the results.

The converter breaks down the number into its three binary parts:

Sign: 0 (positive)
Exponent: -51
Significand: 1.0100000000000000000000000000000000000000000000000000 (binary for 1.2510)

So this number is 1.012 × 2-51, or 1.2510 × 2-51. Since there are only three significant binary digits being stored, that would suggest that Lars may be onto something. They can't be "random noise" since they are the same each time the number is converted.

The data suggests that the only stored digit is "5". The leading zeros come from the exponent and the rest of the seemingly-random digits are from computing 2-51.

Headway answered 2/11, 2009 at 17:57 Comment(4)
Where are all those other digits being stored?Headway
Not, it is the decimal representation of a binary point number. Including it's rounding errors.Bashaw
Wrong: "Leading zeroes don't count" is incorrect. The 15-16 important digits in the answer are 0.0000000000000005. The digits after that are incorrect, and are only present because the rounding errors are promoted into the mantissa because of the leading zeroes. As Barry wrote himself in his edit, the result is stored as 1.25*2^(-51)=5.551*10^(-16), which is a number that has 1 decimal digit of calculation accuracy, but is has 15-16 digits of storage precision.Thickhead
A more interesting behavior appears with Convert.ToSingle("9111111.4999999990") and convert.ToSingle("9111111.4999999991"). Both values are closer to 9111111 than to 9111112, but the latter one rounds up.Poussin
T
17

You should read: What Every Computer Scientist Should Know About Floating-Point Arithmetic .

Basically it comes down to Floating Point numbers being stored with finite precision. You have to do your comparison with some delta.

if(.9 - .8999999999999995 <= 0.0001)
  //close enough to be equal
Tully answered 2/11, 2009 at 17:39 Comment(4)
+1: It is a shame that SO cannot auto-answer with this for each and every floating point question, being the right answer for at least 90% of floating point questions.Desuetude
this doesn't address his question on precision.Jacintojack
-1, does not answer the question. The q is about 32 digits (not 16) for a double.Aphasic
+1 The number of digits is not really the relevant part, it's the method of storage that this answer addresses.Aircondition
P
14

The leading zeros are not significant/part of the precision (as far as the floating point number is concerned -- mathematically speaking, they are significant). The leading zeros are due to the exponent part of the floating point number's internal representation.

The portion 55511151231257827 (which is the significand or mantissa) has 17 decimal digits, which is close enough to 15-16 digits.

@Lars D: What you consider to be correct, is only correct within the context of the question. .9 - .8999999999999995 works out to a float with significand 0.625 and exponent of -50. Taking 0.625 * 2-50 results in 5.5511151231257827e-16. Now, out of the context of the original question, we have a number with 17 significant digits which does happen to be our best binary approximation of 0.0000000000000005. However, those leading zeros are still not significant as far as the representation of the floating point number is concerned.

Pol answered 2/11, 2009 at 17:31 Comment(2)
I downvoted this answer, because I consider your answer incorrect. The 15-16 digits precision in the actual subtraction operation give 0.0000000000000005, and the rest of the digits are random rounding errors. Therefore, in the 55511151231257827 part, there is only 1 correct digit, and the rest are rounding errors, that have been promoted into the mantissa because of the leading zeroes. Basically the 32 digits are 16 significant digits from the subtraction, plus 16 digits of noise in the mantissa afterwards. The zeroes only become insignificant AFTERWARDS, when the result is stored.Thickhead
Right - if I were taking chemistry again, the leading zeros would be significant digits. However, the computer has no concept of whether the zeros should be significant, and that is why there are approximately 16 non-zero digits represented in the answer.Pol
T
4

? .9 - .8999999999999995

This subtraction process, with 15-16 significant digits, gives

0.0000000000000005

The rest of the digits are just rounding errors. However, since the computer always stores 15-16 significant digits after the first non-zero digit, the rounding errors are shown, and you get a lot of trailing random digits produced by rounding errors. So the result has 16 significant digits from the subtraction operation plus 16 digits from the storage of the result, which gives 32 digits.

Thickhead answered 2/11, 2009 at 17:37 Comment(0)
I
3

The "floating" part of "floating point" means that you are getting something closer to 5.5511151231257827 * 10^(-16). That's not exactly how it's represented, because of course it's all done in binary under the hood, but the point is, the number is represented by the significant digits, plus a number which represents how far to move the radix (decimal point). As always, wikipedia can give you more detail:

(The second link is more specifically focused on your particular case.)

Intoxicant answered 2/11, 2009 at 17:41 Comment(0)
B
0

I think its because in the binary system, 5 is periodic as it is not dividable by 2. And then what Mark Rushakoff said applies.

Blond answered 2/11, 2009 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.