Reputation: 1147
I'm using visual studio 2015 to print two floating numbers:
double d1 = 1.5;
double d2 = 123456.789;
std::cout << "value1: " << d1 << std::endl;
std::cout << "value2: " << d2 << std::endl;
std::cout << "maximum number of significant decimal digits (value1): " << -std::log10(std::nextafter(d1, std::numeric_limits<double>::max()) - d1) << std::endl;
std::cout << "maximum number of significant decimal digits (value2): " << -std::log10(std::nextafter(d2, std::numeric_limits<double>::max()) - d2) << std::endl;
This prints the following:
value1: 1.5
value2: 123457
maximum number of significant decimal digits (value1): 15.6536
maximum number of significant decimal digits (value2): 10.8371
Why 123457
is printed out for the value 123456.789
? Does ANSI C++ specification allow to display anything for floating numbers when std::cout
is used without std::setprecision()
?
Upvotes: 19
Views: 70211
Reputation: 328
The rounding off happens because of the C++ standard which can be seen by writing
std::cout<<std::cout.precision();
The output screen will show 6
which tells that the default number of significant digits which will be printed by the std::cout
statement is 6
. That is why it automatically rounds off the floating number to 6 digits.
Upvotes: 12
Reputation: 3121
What you have have pointed out is actually one of those many things that the standardization committee should consider regarding the standard iostream
in C++. Such things work well when you write :-
printf ("%f\n", d2);
But not with std::cout
where you need to use std::setprecision
because it's formatting is similar to the use of %g
instead of %f
in printf
. So you need to write :-
std::cout << std::setprecision(10) << "value2: " << d2 << std::endl;
But if you dont like this method & are using C++11 (& onwards) then you can also write :-
std::cout << "value2: " << std::to_string(d2) << std::endl;
This will give you the same result as printf ("%f\n", d2);
.
A much better method is to cancel the rounding that occurs in std::cout
by using std::fixed
:-
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::fixed;
double d = 123456.789;
std::cout << d;
return 0;
}
Output :-
123456.789000
So I guess your problem is solved !!
Upvotes: 13
Reputation: 129524
I think the problem here is that the C++ standard is not written to be easy to read, it is written to be precise and not repeat itself. So if you look up the operator<<(double)
, it doesn't say anything other than "it uses num_put
- because that is how the cout << some_float_value
is implemented.
The default behaviour is what print("%g", value);
does [table 88 in n3337 version of the C++ standard explains what the equivalence of printf and c++ formatting]. So if you want to do %.16g
you need to change the precision by calling setprecision(16)
.
Upvotes: 3