2

我正在将 C++ 系统从 solaris(SUN box 和 solaris 编译器)转换为 linux(intel box 和 gcc 编译器)。在处理大的“long double”值时,我遇到了几个问题。(由于一些非常非常大的整数,我们使用“long double”......不是任何小数精度)。它以几种奇怪的方式表现出来,但我已将其简化为以下程序。它试图增加一个数字,但没有。我没有得到任何编译或运行时错误......它只是没有增加数字。

我还随机尝试了一些不同的编译器开关(-malign-double 和 -m128bit-long-double 以及这些开关的各种组合打开和关闭),但没有区别。

我也在 gdb 中运行过它,gdb 的“打印”命令显示与 cout 语句相同的值。

有人见过这种行为吗?

谢谢

编译命令

$ /usr/bin/c++ --version
c++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4)

$ /usr/bin/c++ -g -Wall -fPIC   -c SimpleLongDoubleTest.C   -o SimpleLongDoubleTest.o

$ /usr/bin/c++ -g SimpleLongDoubleTest.o   -o SimpleLongDoubleTest

$ ./SimpleLongDoubleTest
Maximum value for long double: 1.18973e+4932
digits 10 = 18
ld = 1268035319515045691392
ld = 1268035319515045691392
ld = 1268035319515045691392
ld = 1268035319515045691392
ld = 1268035319515045691392

SimpleLongDoubleTest.C

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <limits>
#include <iomanip>

int main( int argc, char* argv[] )
{
    std::cout << "Maximum value for long double: " 
              << std::numeric_limits<long double>::max() << '\n';

    std::cout << "digits 10 = " << std::numeric_limits<long double>::digits10 
              << std::endl;

    // this doesn't work  (there might be smaller numbers that also doen't work...
    // That is, I'm not sure the exact number between this and the number defined
    // below where things break)
      long double ld = 1268035319515045691392.0L ;

    // but this or any smaller number works (there might be larger numbers that
    // work... That is, I'm not sure the exact number between this and the number
    // defined above where things break)
    //long double ld =  268035319515045691392.0L ;

    for ( int i = 0 ; i < 5 ; i++ )
    {
        ld++ ;

        std::cout << std::setiosflags( std::ios::fixed ) 
                  << std::setprecision( 0 ) 
                  << "ld = "  <<    ld
                  << std::endl ;
    }
}
4

1 回答 1

2

这是预期的行为。浮点数、双精度、长双精度等在内部以 (2^exp-bias)*1 + xxxxx 的形式表示,其中 xxxxx 是 N 位二进制数,其中 N=23 表示浮点数,52 表示双精度,可能 64 表示长双打。当数字增长大于 2^N 时,不再可能向该变量添加“1”——只能添加 2^(nN) 的倍数。

您的架构也可能将 long double 等同于 double。(即使 x86 可以在内部使用 80 位双精度数)。

另请参阅Wikipedia 文章- 128 位双精度是一个例外而不是常态。(sparc 支持它)。

于 2013-04-22T16:59:58.777 回答