本文翻译自:How do I print a double value with full precision using cout?
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. 我正在使用使用cout打印的double cout ,当我没想到时会四舍五入。 How can I make cout print a double using full precision? 如何使cout以全精度打印double ?
参考:https://stackoom.com/question/2K8V/如何使用cout以全精度打印双精度值
With ostream::precision(int) 使用ostream :: precision(int)
cout.precision( numeric_limits<double>::digits10 + 1); cout << M_PI << ", " << M_E << endl;will yield 将产生
3.141592653589793, 2.718281828459045Why you have to say "+1" I have no clue, but the extra digit you get out of it is correct. 为什么您必须说“ +1”我不知道,但是您从中得到的多余数字是正确的。
%.12f表示浮点数,精度为12位数字。
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. 就全精度而言,我假设平均精度足以显示与预期值的最佳近似值,但是应该指出,使用基数2表示存储double精度数,而基数2不能精确表示1.1 。 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). 获得实际双精度全精度的唯一方法(不带ROUND OFF ERROR)是打印出二进制位(或十六进制小数位)。 One way of doing that is writing the double to a union and then printing out the integer value of the bits. 一种方法是将double写入并union ,然后打印出这些位的整数值。
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 ! 这将为您提供double的100%准确的精度...并且完全无法读取,因为人类无法阅读IEEE double格式! Wikipedia has a good write up on how to interpret the binary bits. 维基百科对如何解释二进制位有很好的记录。
In newer C++, you can do 在较新的C ++中,您可以执行
std::cout << std::hexfloat << 1.1;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 100.0000000000005
max_digits10 is the number of digits that are necessary to uniquely represent all distinct double values. max_digits10是唯一表示所有不同的double值所必需的位数。 max_digits10 represents the number of digits before and after the decimal point. max_digits10代表小数点前后的位数。
Don't use set_precision(max_digits10) with std::fixed. 不要将set_precision(max_digits10)与std :: fixed一起使用。 On fixed notation, set_precision() sets the number of digits only after the decimal point. 使用固定表示法时,set_precision() 仅在小数点后设置位数。 This is incorrect as max_digits10 represents the number of digits before and after the decimal point. 这是不正确的,max_digits10代表前和小数点后的位数。
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 100.00000000000049738
Note: Header files required 注意:需要头文件
#include <iomanip> #include <limits>How do I print a double value with full precision using cout? 如何使用cout以全精度打印double精度值?
Use hexfloat or 使用hexfloat或 use scientific and set the precision 用scientific设定精度
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-01Too many answers address only one of 1) base 2) fixed/scientific layout or 3) precision. 答案太多,只能解决1)基本2)固定/科学布局或3)精度之一。 Too many answers with precision do not provide the proper value needed. 太多的精确答案无法提供所需的正确值。 Hence this answer to a old question. 因此,这个答案是一个古老的问题。
What base? 什么基础?A double is certainly encoded using base 2. A direct approach with C++11 is to print using std::hexfloat . 一个double肯定是使用base 2编码的。C ++ 11的直接方法是使用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+144A double is a floating point type, not fixed point . double是浮点类型,而不是固定点类型。
Do not use std::fixed as that fails to print small double as anything but 0.000...000 . 不要使用std::fixed为无法打印小double是什么,但0.000...000 。 For large double , it prints many digits, perhaps hundreds of questionable informativeness. 对于大的double ,它会打印许多数字,也许有成百上千的可疑信息。
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.000000To print with full precision, first use std::scientific which will "write floating-point values in scientific notation". 要以全精度打印,请首先使用std::scientific ,它将“以科学计数法编写浮点值”。 Notice the default of 6 digits after the decimal point, an insufficient amount, is handled in the next point. 请注意,小数点后的默认6位数字不足,将在下一点处理。
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+43A double encoded using the binary base 2 encodes the same precision between various powers of 2. This is often 53 bits. 使用二进制基数2进行的double精度编码在2的乘方幂之间具有相同的精度。通常为53位。
[1.0...2.0) there are 2 53 different double , [1.0 ... 2.0)有2 53个不同的double , [2.0...4.0) there are 2 53 different double , [2.0 ... 4.0)有2 53个不同的double , [4.0...8.0) there are 2 53 different double , [4.0 ... 8.0)有2 53个不同的double , [8.0...10.0) there are 2/8 * 2 53 different double . [8.0 ... 10.0)有2/8 * 2 53个不同的double 。
Yet if code prints in decimal with N significant digits, the number of combinations [1.0...10.0) is 9/10 * 10 N . 但是,如果代码以N有效数字十进制打印,则组合[1.0 ... 10.0)的数量为9/10 * 10 N。
Whatever N (precision) is chosen, there will not be a one-to-one mapping between double and decimal text. 无论N (精度)被选择,不会有间的一种一对一映射double和小数文本。 If a fixed N is chosen, sometimes it will be slightly more or less than truly needed for certain double values. 如果选择一个固定的N ,则有时它会比某些double值的实际需要稍微多一些或少一些。 We could error on too few ( a) below) or too many ( b) below). 我们可能会在下面的( b)太少或下面的( b)太多a)中出错。
3 candidate N : 3名候选人N :
a) Use an N so when converting from text- double -text we arrive at the same text for all double . a)使用的N从文本的转换时,使double ,我们在所有相同的文本到达-text double 。
std::cout << dbl::digits10 << '\n'; // Typical output 15b) Use an N so when converting from double -text- double we arrive at the same double for all double . B)使用N所以从转换时, double -text- double ,我们到达同一double所有double 。
// C++11 std::cout << dbl::max_digits10 << '\n'; // Typical output 17When 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. 当max_digits10不可用时,请注意由于以2和10为底的属性digits10 + 2 <= max_digits10 <= digits10 + 3 ,我们可以使用digits10 + 3来确保打印足够的十进制数字。
c) Use an N that varies with the value. c)使用随值变化的N
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 ). 当代码想要显示最少的文本( N == 1 )或double denorm_min的精确值( denorm_min N == 1000-ish ,这denorm_min 。 Yet since this is "work" and not likely OP's goal, it will be set aside. 然而,由于这是“工作”,而不是OP的目标,因此将其搁置一旁。
It is usually b) that is used to "print a double value with full precision". 通常是b)用于“以全精度打印double精度值”。 Some applications may prefer a) to error on not providing too much information. 某些应用程序可能更喜欢a)由于没有提供太多信息而出错。
With .scientific , .precision() sets the number of digits to print after the decimal point, so 1 + .precision() digits are printed. 使用.scientific , .scientific .precision()设置要在小数点后打印的位数,因此将打印1 + .precision()位数。 Code needs max_digits10 total digits so .precision() is called with a max_digits10 - 1 . 代码总共需要max_digits10个数字,因此max_digits10会调用max_digits10 - 1 .precision() 。
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 digitsSimilar C question 相似的C问题