4

次のようなコードセグメントを考えると、私は知りたいだけです

  • long doubleの最大値が32ビットより64ビットの方が小さいのはなぜですか?
  • なぜ64ビットバージョンは「40」精度の出力を満たすために32ビットバージョンほど多くの桁を拡張できないのですか?
  • LDBL_MINとLDBL_MAXの値が等しいようですが、それはバグですか?

マシンのfloat.hファイルを調べましたが、これらのマクロ定数の明示的な定義が見つかりません。

テストコード(プラットフォーム= Win7-64ビット)

#include <cfloat>
#include <iomanip>
cout<<"FLT_MAX   ="<< setprecision(40) << FLT_MAX  << endl;
cout<<"DBL_MAX   ="<< setprecision(40) << DBL_MAX  << endl;
cout<<"LDBL_MAX  ="<< setprecision(40) << LDBL_MAX << endl;
cout<<"FLT_MIN   ="<< setprecision(40) << FLT_MIN  << endl;
cout<<"DBL_MIN   ="<< setprecision(40) << DBL_MIN  << endl;
cout<<"LDBL_MIN  ="<< setprecision(40) << LDBL_MIN << endl;

32ビットの結果(MinGW-20120426)

FLT_MAX  =340282346638528859811704183484516925440
DBL_MAX  =1.797693134862315708145274237317043567981e+308
LDBL_MAX =1.189731495357231765021263853030970205169e+4932
FLT_MIN  =1.175494350822287507968736537222245677819e-038
DBL_MIN  =2.225073858507201383090232717332404064219e-308
LDBL_MIN =3.362103143112093506262677817321752602598e-4932

64ビットの結果(MinGW64-TDM 4.6)

FLT_MAX  =340282346638528860000000000000000000000
DBL_MAX  =1.7976931348623157e+308
LDBL_MAX =1.132619801677474e-317
FLT_MIN  =1.1754943508222875e-038
DBL_MIN  =2.2250738585072014e-308
LDBL_MIN =1.132619801677474e-317

ありがとう。

[編集]:最新のMinGW64-TGM 4.7.1を使用すると、LDBL_MAX、LDBL_MINの「バグ」が削除されたようです。

4

2 に答える 2

3

LDBL_MAX =1.132619801677474e-317どこかのバグのように聞こえます。doubleとして表現可能なすべての値は としても表現できることが標準の要件であるlong doubleため、 では許可されませんLDBL_MAX < DBL_MAX。実際のテスト コードを示していないことを考えると、コンパイラを非難する前に、個人的にそれを確認します。

2 つの間に (バグではない) 違いがlong doubleある場合、その違いの根拠は、32 ビット コンパイラが 80 ビットの精度を持つ古い x87 浮動小数点演算を使用しているため、80 を許可することです。 -ビットlong double

64 ビット コンパイラは、x64 で新しい 64 ビット浮動小数点演算を使用します。80 ビットの精度はなく、x87 命令に切り替えてより大きなlong double.

おそらくそれ以上の複雑さがあります。たとえば、すべての x86 コンパイラが必ずしも 80 ビットのlong double. 彼らがどのようにその決定を下すかは、おそらく SSE2 に 64 ビット浮動小数点演算があるという事実を含め、さまざまなことに依存します。しかし、可能性long doubleとしては と同じサイズdoubleか、それよりも大きい可能性があります。

「40」精度の出力を満たすために、64ビットバージョンが32ビットバージョンほど多くの桁を拡張できないのはなぜですか?

double の精度は 10 進数で約 15 桁です。それを超える数字は有益な場合もありますが、通常は誤解を招きます。

標準が について何を言っているのか思い出せませんsetprecisionが、実装が数字の生成を停止する線を描くことが許可されていると仮定すると、 a の精度はdoubleそれを描くのに妥当な場所です。1 つの実装が実際にそれを行うことに決めたのに、もう 1 つの実装がそうしなかった理由については、わかりません。それらは異なるディストリビューションであるため、まったく異なる標準ライブラリを使用している可能性があります。

同じ「疑似精度」が、340282346638528859811704183484516925440ある場合には FLT_MAX が表示される理由ですが340282346638528860000000000000000000000、別の場合には表示されます。1 つのコンパイラ (または 1 つのライブラリの実装) が、多くの桁数を計算するのに苦労しました。もう一人は早々に諦めて丸めました。

于 2012-10-03T10:55:59.690 に答える
0

この質問に答えるために、私はいくつかの仮定のみを行います: 1) これを 64 ビット マシンでのみテストしたこと 2) コンパイラは同じサブバージョンの異なるビット バージョンである (つまり、実質的に姉妹コンパイラである) )。

それは言われた:

「ISO/IEC 14882 INTERNATIONAL STANDARD First edition 1998-09-01」より

3.9.1 基本型

  1. 浮動小数点型には、float、double、long double の 3 つがあります。double 型は少なくとも float と同じ精度を提供し、型 long double は少なくとも double と同じ精度を提供します。float 型の値のセットは、double 型の値のセットのサブセットです。double 型の値のセットは、long double 型の値のセットのサブセットです。浮動小数点型の値表現は実装定義です。整数型と浮動小数点型をまとめて算術型と呼びます。標準テンプレート numeric_limits (18.2) の特殊化は、実装の各算術型の最大値と最小値を指定するものとします。

さらに、CPU が異なれば、レベル数が高い場合の精度に関しても、最終結果にさまざまな影響があります。コンパイラも同様です。VC++ のコンパイラは、borland や GCC/G++ などと同じように動作しません。

于 2012-10-03T10:33:39.813 に答える