1

我有一个long double常量,我将其设置为 const 或非 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 或其他库,但我很好奇是什么原因造成的。感谢您的洞察力。

4

2 回答 2

10

我得到这个输出:

19
const via cout: 0.6931471805599453094
non-const via cout: 0.6931471805599453094
const via printf: 0.6931471805599453094
non-const via printf: 0.6931471805599453094

但我使用的是 long double 文字而不是 double 文字:

const long double constLog2 = 0.6931471805599453094172321214581765680755L;
long double log2 = 0.6931471805599453094172321214581765680755L;    
于 2009-03-26T01:03:49.150 回答
4

有一些与硬件平台和编译选项相关的微妙问题可能会引起人们的兴趣:

这些 `-m' 选项是为 i386 和 x86-64 系列计算机定义的:

-m96bit-long-double

-m128bit-long-double

这些开关控制 long double 类型的大小。i386 应用程序二进制接口指定大小为 96 位,因此 -m96bit-long-double 是 32 位模式下的默认值。现代架构(奔腾和更新)更喜欢 long double 对齐到 8 或 16 字节边界。在符合 ABI 的数组或结构中,这是不可能的。因此,指定 -m128bit-long-double 会将 long double 与 16 字节边界对齐,方法是用额外的 32 位零填充 long double。

在 x86-64 编译器中,-m128bit-long-double 是默认选择,因为它的 ABI 指定 long double 将在 16 字节边界上对齐。

请注意,这些选项都没有为 long double 启用超过 80 位的 x87 标准的任何额外精度。

警告:如果您覆盖目标 ABI 的默认值,则包含 long double 变量的结构和数组将改变它们的大小,并且函数采用 long double 的函数调用约定将被修改。因此,它们不会与在没有该开关的情况下编译的代码中的数组或结构二进制兼容。

于 2009-03-26T01:13:06.023 回答