Re: Convert float to double - weird failure



"Richard Heathfield" <rjh@xxxxxxxxxxxxxxx> wrote in message
news:T5idnXm9KMoJRL7aRVnyuwA@xxxxxxxxx
tugboat90 said:

<snips>

Thank you for the responses, but I understand how the numbers are
represented inside of a computer. I think I phrased my question
wrong.

You seem to have misunderstood the answers, too, because the answer to
your
question is indeed to do with how numbers are represented inside a
computer. BUT if you meant to ask why std::cout didn't interpret the
number in the way you expected, see the end of this article.

But why? Let's see.

We know that we can represent 1 exactly, so let's reduce the problem to
that of representing 0.2 (that is, one fifth) exactly. To try to do this,
we'll use binary representation, with each column to the right of the
radix point having half the value of the column to its left. So 0.1 means
a half, 0.01 means a quarter, 0.001 means an eighth, and so on.

Now let's use a binary search technique to narrow quickly onto the exact
representation of one fifth. We'll get as close as we can with one bit,
then with two, and so on.

0.1 = 1/2 = 0.5 - too large
0.01 = 1/4 = 0.25 - too large
0.001 = 1/8 = 0.125 - too small
0.0011 = 3/16 = 0.1875 - too small
0.00111 = 7/32 = 0.21875 - too large
0.001101 = 13/64 = 0.203125 - too large
0.0011001 = 25/128 = 0.1953125 - too small
0.00110011 = 51/256 = 0.19921875 - too small
0.001100111 = 103/512 = 0.201171875 - too large
0.0011001101 = 205/1024 = 0.2001953125 - too large
0.00110011001 = 409/2048 = 0.19970703125 - too small
0.001100110011 = 819/4096 = 0.199951171875 - too small
0.0011001100111 = 1639/8192 = 0.2000732421875 - too large
0.00110011001101 = 3277/16384 = 0.20001220703125 - too large
0.001100110011001 = 6553/32768 = 0.199981689453125 - too small
0.0011001100110011 = 13107/65536 = 0.1999969482421875 - too small

The pattern is clear. You need an infinite number of 0011 repeats if you
want to get exactly one fifth. Computers don't have infinite storage, so
the computer has to use the best approximation it can.


Excellent demonstration Richard.

With the floating point system he seems to be using, we can also show why he
gets a slightly larger answer. The computer doesn't store binary points and
it scales the value to remove leading zeros. So we end up with a pattern
such as 110011001100110011001100... from your binary values above.

Unless there is over/under flow the first 1 isn't stored so we up with
1001100110011001100110011001 ... which broken up in 4-bit chunks becomes
1001 1001 1001 1001 1001 1001 1001 but you have to stop somewhere. Now
looking at the first 25 bits we round this up to
1001 1001 1001 1001 1001 1010 (since the 25th bit is a 1) which now makes
the value a little larger. The digits he calls garbage are not garbage, they
are the exact binary value the computer got when it converted from decimal
to binary. The same type of problems occur even if you use BCD (used in a
standard calculator) as others have pointed out.


.


Quantcast