1

long doubleconst または 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 や他のライブラリを調べることはできますが、何が原因なのか知りたいです。あなたの洞察に感謝します。

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

しかし、私は二重リテラルの代わりに長い二重リテラルを使用しています:

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 ビット モードのデフォルトです。最新のアーキテクチャ (Pentium 以降) では、long double を 8 または 16 バイト境界に揃えることを好みます。ABI に準拠する配列または構造体では、これは不可能です。したがって、-m128bit-long-double を指定すると、long double に 32 ビットのゼロが追加されて、long double が 16 バイト境界に揃えられます。

x86-64 コンパイラでは、-m128bit-long-double がデフォルトの選択です。これは、その ABI が long double を 16 バイト境界に揃えることを指定しているためです。

これらのオプションのどちらも、long double の 80 ビットの x87 標準を超える精度を有効にしないことに注意してください。

警告: ターゲット ABI のデフォルト値をオーバーライドすると、long double 変数を含む構造体と配列のサイズが変更され、long double を取る関数の関数呼び出し規約が変更されます。したがって、そのスイッチなしでコンパイルされたコードの配列または構造体とのバイナリ互換性はありません。

于 2009-03-26T01:13:06.023 に答える