Re: Convert float to double - weird failure
- From: Richard Heathfield <rjh@xxxxxxxxxxxxxxx>
- Date: Sun, 28 Oct 2007 00:39:28 +0000
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.
When I converted from a float to a double, why did it add random junk
at the end of the number instead of making it zeros? If the random
junk is there, how do I get rid of it?
Here's your original code:
Example:
// Define a float
float f = 1.20000;
// Cast into a double - after the cast, the value of "d" is
// is "1.20000498297"
double d = static_cast<double> (f);
Firstly, let's get rid of the idea that it's the cast that's the problem.
(You have to promise not to laugh at my C++, though. I'm not a great fan
of iostreams, and it probably shows.)
#include <iostream>
#include <iomanip>
int main()
{
float f = 1.20000;
double d = static_cast<double> (f);
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint)
<< std::setprecision(16)
<< "double d has the value "
<< d
<< std::endl;
std::cout << "float f has the value " << f << std::endl;
return 0;
}
The output from this program is:
double d has the value 1.2000000476837158
float f has the value 1.2000000476837158
So it isn't the cast, okay? The float has the same problem.
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.
Now, if your question is "why didn't std::cout round my result?", the
answer is simple: std::cout is not a mind-reader. If you want it to
display a round number, you're going to have to tell it how to do the
rounding. Look up <iomanip> in your C++ reference book.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
.
- Follow-Ups:
- Re: Convert float to double - weird failure
- From: bill robertson
- Re: Convert float to double - weird failure
- References:
- Convert float to double - weird failure
- From: tugboat90
- Re: Convert float to double - weird failure
- From: mike3
- Re: Convert float to double - weird failure
- From: tugboat90
- Convert float to double - weird failure
- Prev by Date: Re: Convert float to double - weird failure
- Next by Date: Re: Convert float to double - weird failure
- Previous by thread: Re: Convert float to double - weird failure
- Next by thread: Re: Convert float to double - weird failure
- Index(es):
Relevant Pages
|