长双输出的精度不正确。可能有什么问题?

时间:2009-03-26 00:54:12

标签: c++ precision math long-double

我有一个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或其他库,但我很好奇是什么导致了这一点。感谢您的见解。

2 个答案:

答案 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将被修改。因此他们   不会二进制兼容   编译的代码中的数组或结构   没有那个开关。