How do I print a double value with full precision using cout?

早过忘川 提交于 2019-11-25 22:16:54

问题


So I\'ve gotten the answer to my last question (I don\'t know why I didn\'t think of that). I was printing a double using cout that got rounded when I wasn\'t expecting it. How can I make cout print a double using full precision?


回答1:


You can set the precision directly on std::cout and use the std::fixed format specifier.

double d = 3.14159265358979;
cout.precision(17);
cout << "Pi: " << fixed << d << endl;

You can #include <limits> to get the maximum precision of a float or double.

#include <limits>

typedef std::numeric_limits< double > dbl;

double d = 3.14159265358979;
cout.precision(dbl::max_digits10);
cout << "Pi: " << d << endl;



回答2:


Use std::setprecision:

std::cout << std::setprecision (15) << 3.14159265358979 << std::endl;



回答3:


Here is what I would use:

std::cout << std::setprecision (std::numeric_limits<double>::digits10 + 1)
          << 3.14159265358979
          << std::endl;

Basically the limits package has traits for all the build in types.
One of the traits for floating point numbers (float/double/long double) is the digits10 attribute. This defines the accuracy (I forget the exact terminology) of a floating point number in base 10.

See: http://www.cplusplus.com/reference/std/limits/numeric_limits.html
For details about other attributes.




回答4:


The iostreams way is kind of clunky. I prefer using boost::lexical_cast because it calculates the right precision for me. And it's fast, too.

#include <string>
#include <boost/lexical_cast.hpp>

using boost::lexical_cast;
using std::string;

double d = 3.14159265358979;
cout << "Pi: " << lexical_cast<string>(d) << endl;

Output:

Pi: 3.14159265358979




回答5:


By full precision, I assume mean enough precision to show the best approximation to the intended value, but it should be pointed out that double is stored using base 2 representation and base 2 can't represent something as trivial as 1.1 exactly. The only way to get the full-full precision of the actual double (with NO ROUND OFF ERROR) is to print out the binary bits (or hex nybbles). One way of doing that is writing the double to a union and then printing out the integer value of the bits.

union {
    double d;
    uint64_t u64;
} x;
x.d = 1.1;
std::cout << std::hex << x.u64;

This will give you the 100% accurate precision of the double... and be utterly unreadable because humans can't read IEEE double format ! Wikipedia has a good write up on how to interpret the binary bits.

In newer C++, you can do

std::cout << std::hexfloat << 1.1;



回答6:


Here is how to display a double with full precision:

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::setprecision(precision) << d << std::endl;

This displays:

100.0000000000005


max_digits10 is the number of digits that are necessary to uniquely represent all distinct double values. max_digits10 represents the number of digits before and after the decimal point.


Don't use set_precision(max_digits10) with std::fixed.
On fixed notation, set_precision() sets the number of digits only after the decimal point. This is incorrect as max_digits10 represents the number of digits before and after the decimal point.

double d = 100.0000000000005;
int precision = std::numeric_limits<double>::max_digits10;
std::cout << std::fixed << std::setprecision(precision) << d << std::endl;

This displays incorrect result:

100.00000000000049738

Note: Header files required

#include <iomanip>
#include <limits>



回答7:


How do I print a double value with full precision using cout?

Use hexfloat or
use scientific and set the precision

std::cout.precision(std::numeric_limits<double>::max_digits10 - 1);
std::cout << std::scientific <<  1.0/7.0 << '\n';

// C++11 Typical output
1.4285714285714285e-01

Too many answers address only one of 1) base 2) fixed/scientific layout or 3) precision. Too many answers with precision do not provide the proper value needed. Hence this answer to a old question.

  1. What base?

A double is certainly encoded using base 2. A direct approach with C++11 is to print using std::hexfloat.
If a non-decimal output is acceptable, we are done.

std::cout << "hexfloat: " << std::hexfloat << exp (-100) << '\n';
std::cout << "hexfloat: " << std::hexfloat << exp (+100) << '\n';
// output
hexfloat: 0x1.a8c1f14e2af5dp-145
hexfloat: 0x1.3494a9b171bf5p+144

  1. Otherwise: fixed or scientific?

A double is a floating point type, not fixed point.

Do not use std::fixed as that fails to print small double as anything but 0.000...000. For large double, it prints many digits, perhaps hundreds of questionable informativeness.

std::cout << "std::fixed: " << std::fixed << exp (-100) << '\n';
std::cout << "std::fixed: " << std::fixed << exp (+100) << '\n';
// output
std::fixed: 0.000000
std::fixed: 26881171418161356094253400435962903554686976.000000 

To print with full precision, first use std::scientific which will "write floating-point values in scientific notation". Notice the default of 6 digits after the decimal point, an insufficient amount, is handled in the next point.

std::cout << "std::scientific: " << std::scientific << exp (-100) << '\n';  
std::cout << "std::scientific: " << std::scientific << exp (+100) << '\n';
// output
std::scientific: 3.720076e-44
std::scientific: 2.688117e+43

  1. How much precision (how many total digits)?

A double encoded using the binary base 2 encodes the same precision between various powers of 2. This is often 53 bits.

[1.0...2.0) there are 253 different double,
[2.0...4.0) there are 253 different double,
[4.0...8.0) there are 253 different double,
[8.0...10.0) there are 2/8 * 253 different double.

Yet if code prints in decimal with N significant digits, the number of combinations [1.0...10.0) is 9/10 * 10N.

Whatever N (precision) is chosen, there will not be a one-to-one mapping between double and decimal text. If a fixed N is chosen, sometimes it will be slightly more or less than truly needed for certain double values. We could error on too few (a) below) or too many (b) below).

3 candidate N:

a) Use an N so when converting from text-double-text we arrive at the same text for all double.

std::cout << dbl::digits10 << '\n';
// Typical output
15

b) Use an N so when converting from double-text-double we arrive at the same double for all double.

// C++11
std::cout << dbl::max_digits10 << '\n';
// Typical output
17

When max_digits10 is not available, note that due to base 2 and base 10 attributes, digits10 + 2 <= max_digits10 <= digits10 + 3, we can use digits10 + 3 to insure enough decimal digits are printed.

c) Use an N that varies with the value.

This can be useful when code wants to display minimal text (N == 1) or the exact value of a double (N == 1000-ish in the case of denorm_min). Yet since this is "work" and not likely OP's goal, it will be set aside.


It is usually b) that is used to "print a double value with full precision". Some applications may prefer a) to error on not providing too much information.

With .scientific, .precision() sets the number of digits to print after the decimal point, so 1 + .precision() digits are printed. Code needs max_digits10 total digits so .precision() is called with a max_digits10 - 1.

typedef std::numeric_limits< double > dbl;
std::cout.precision(dbl::max_digits10 - 1);
std::cout << std::scientific <<  exp (-100) << '\n';
std::cout << std::scientific <<  exp (+100) << '\n';
// Typical output
3.7200759760208361e-44
2.6881171418161356e+43
//1234567890123456  17 total digits

Similar C question




回答8:


printf("%.12f", M_PI);

%.12f means floating point, with precision of 12 digits.




回答9:


Most portably...

#include <limits>

using std::numeric_limits;

    ...
    cout.precision(numeric_limits<double>::digits10 + 1);
    cout << d;



回答10:


With ostream::precision(int)

cout.precision( numeric_limits<double>::digits10 + 1);
cout << M_PI << ", " << M_E << endl;

will yield

3.141592653589793, 2.718281828459045

Why you have to say "+1" I have no clue, but the extra digit you get out of it is correct.



来源:https://stackoverflow.com/questions/554063/how-do-i-print-a-double-value-with-full-precision-using-cout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!