Let’s,
float dt;
I read dt from a text file as
inputFile >> dt;
Then I have a for loop as,
for (float time=dt; time<=maxTime; time+=dt)
{
// some stuff
}
When dt=0.05 and I output std::cout << time << std::endl; I got,
0.05
0.10
...
7.00001
7.05001
...
So, why number of digits is increasing after a while?
Because not every number can be represented by IEEE754 floating point values. At some point, you’ll get a number that isn’t quite representable and the computer will have to choose the nearest one.
If you enter 0.05 into
Harald Schmidt's excellent online converterand reference the Wikipedia entry on IEEE754-1985, you’ll end up with the following bits (my explanation of that follows):The sign, being 0, is positive. The exponent is indicated by the one-bits mapping to the numbers on the left:
64+32+16+8+2 = 122 - 127 bias = -5, so the multiplier is 2-5 or1/32. The127bias is to allow representation of very small numbers (as in close to zero rather that negative numbers with a large magnitude).The mantissa is a little more complicated. For each one-bit, you accumulate the numbers down the right hand side (after adding an implicit
1). Hence you can calculate the number as the sum of{1, 1/2, 1/16, 1/32, 1/256, 1/512, 1/4096, 1/8192, 1/65536, 1/131072, 1/1048576, 1/2097152, 1/8388608}.When you add all these up, you get
1.60000002384185791015625.When you multiply that by the multiplier
1/32(calculated previously from the exponent bits), you get0.0500000001, so you can see that0.05is already not represented exactly. This bit pattern for the mantissa is actually the same as0.1but, with that, the exponent is -4 rather than -5, and it’s why0.1 + 0.1 + 0.1is rarely equal to0.3(this appears to be a favourite interview question).When you start adding them up, that small error will accumulate since, not only will you see an error in the
0.05itself, errors may also be introduced at each stage of the accumulation – not all the the numbers0.1,0.15,0.2and so on can be represented exactly either.Eventually, the errors will get large enough that they’ll start showing up in the number if you use the default precision. You can put this off for a bit by choosing your own precision with something like:
It won’t fix the variable value, but it will give you some more breathing space before the errors become visible.