std::cout does not print float as excepted

Viewed 271

Why does std::cout << 1.00000001; print 1 to the console? It Works fine with 1.0001, Its only after it exceeds a certain precision when it stops printing it properly.

These numbers are hard coded, so this question is not a duplicate. In that question, an irrational number was produced because two floating point numbers were added, which means the numbers could not be stored properly, but in my case the numbers are hard coded, so what is the reason for not being able to print (or store maybe) a float explicitly initialised as 1.00000001?. Is it just cout failing to print the value or is it really an int?

Consider the following program

int main()
{
    float num = 1.0000001f;
    float num2 = num * 2;
    std::cout << num;
    std::cout << num2;
}

num2 prints 2 but the complier does not give a warning about conversion from float to int in line 2, so I think that num must be a float. Does that mean it's just a problem with cout? Am I safe to assume that internally num is actually 1.0000001f even though it prints 1 to the console?

My complier is visual studio 2019's inbuilt one.

2 Answers

Summarizing my comments:

  • The number 1.0000001 cannot be represented by a float.
  • The compiler will pick a float value.
  • It can round however it wants (up, down or closest), that's implementation-defined.

So if you play a bit with this converter, you can see that after 1, the next float values are:

  • 1
  • 1.00000011920928955078125
  • 1.0000002384185791015625
  • 1.00000035762786865234375
  • 1.000000476837158203125
  • ...

1.0000001 falls in between the first two, so your compiler can choose either. In your case it seems your compiler picked 1.

(also for printing operations, cout operations will truncate digits after a defined precision, so it does not show the full numbers I put above - that precision defaults to 6 digits).

The default precision I believe is 6 digits for you, but they are all zeroes. So they don't print.

#include <iostream>
#include <iomanip>

int main()
{
    std::cout << std::setprecision(10);

    // this is what you had
    float f1 = 1.0000001f;
    float f2 = f1 * 2;
    std::cout << f1 << std::endl;
    std::cout << f2 << std::endl;

    // any more zeroes and it would have been idistinguishable from 1.0
    f1 = 1.00000001f;
    f2 = f1 * 2;
    std::cout << f1 << std::endl;
    std::cout << f2 << std::endl;
}

1.000000119
2.000000238
1
2

Related