我有一个long double
常量,我将其设置为const或not-const。它比我测试工作站上long double
的精度(19位)更长(40位)。
当我打印出来时,它不再以19位精度显示,而是以16位显示。
以下是我正在测试的代码:
#include <iostream>
#include <iomanip>
#include <limits>
#include <cstdio>
int main ()
{
const long double constLog2 = 0.6931471805599453094172321214581765680755;
long double log2 = 0.6931471805599453094172321214581765680755;
std::cout << std::numeric_limits<long double>::digits10 + 1 << std::endl;
std::cout << "const via cout: " << std::setprecision(19) << constLog2 << std::endl;
std::cout << "non-const via cout: " << std::setprecision(19) << log2 << std::endl;
std::fprintf(stdout, "const via printf: %.19Lf\n", constLog2);
std::fprintf(stdout, "non-const via printf: %.19Lf\n", log2);
return 0;
}
编译:
$ g++ -Wall precisionTest.cpp
输出:
$ ./a.out
19
const via cout: 0.6931471805599452862
non-const via cout: 0.6931471805599452862
const via printf: 0.6931471805599452862
non-const via printf: 0.6931471805599452862
我希望0.6931471805599453094
,而是获得0.6931471805599452862
。
是否有理由将19位精度切割为16位?
这是我的环境:
$ gcc --version
i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5490)
我看到其他版本的gcc存在同样的问题,例如:
$ gcc --version
g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-10)
我可以查看NTL或其他库,但我很好奇是什么导致了这一点。感谢您的见解。
答案 0 :(得分:10)
我得到了这个输出:
19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094
但我使用的是长双重文字而不是双重文字:
const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;
答案 1 :(得分:4)
有一些与硬件平台和编译选项有关的微妙问题可能会引起关注:
http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html
3.17.3 Intel 386 and AMD x86-64 Options (gcc-4.0.1)
这些`-m'选项是为i386和x86-64系列计算机定义的:
-m96bit - 长 - 双
-m128bit - 长 - 双
这些开关控制long double类型的大小。 i386应用程序二进制接口 指定大小为96位,所以 -m96bit-long-double是32位模式的默认值。现代建筑 (奔腾和更新)宁愿长 double可以与8或16对齐 字节边界。在数组或结构中 符合ABI,这不会 有可能。所以指定一个 -m128bit-long-double将长双精度对齐到16字节边界 用一个填充长双 额外的32位零。
在x86-64编译器中, -m128bit-long-double是默认选项,因为它的ABI指定了long double将在16字节上对齐 边界。
请注意,这些选项都不是 实现任何额外的精度 x87标准的80位长 双。
警告:如果覆盖默认值 你的目标ABI的价值 结构和包含long的数组 双变量会改变他们的 大小以及函数调用 功能的约定很长 double将被修改。因此他们 不会二进制兼容 编译的代码中的数组或结构 没有那个开关。