2017-03-23 4 views
1

これは、ANSI Cコードです:このコードのdouble&long double:コンピュータ上で同じですか?

float  x = 3.14159264351134890172; 
    double  y = 3.14159264351134890172; 
    long double z = 3.14159264351134890172; 

    printf("%f\n",x); 
    printf("%f\n",y); 
    printf("%f\n",z); 
    printf("%.20f\n",x); 
    printf("%.20f\n",y); 
    printf("%.20f\n",z); 

出力は次のとおりです。

3.141593 
3.141593 
3.141593 
3.14159274101257324219 
3.14159264351134881466 
3.14159264351134881466 

は、最後の出力行を参照してください。私はlong doubleが小数点以下19桁の精度を与えることを読んだ。しかし、ここで私は小数点以下15桁の精度を取得します。私のコンピュータにはdoublelong doubleの間に違いはありません。 CentOSでlinuxカーネル2.6.32-358.el6.x86_64を使用しています。 私のCコンパイラはgcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

なぜそうですか?それがコンピュータのハードウェア/アーキテクチャに依存する場合、どのように長い倍精度が倍精度よりも大きい私のLinuxマシンを購入するのですか? 私のCコンパイラにも依存しますか?はいの場合、Cコンパイラはどのように選択しますか?

floatの場合、値の範囲は1.2E-38 to 3.4E+38です。ぜんぜんわかりません。上の例から、float変数に3.1415926のような小数の10進数を正しく格納することはできません。マシンは変数floatに3.141592しか正しく格納されません。だから私は最後の7桁を失ってしまった。ここは6だ。それでは、なぜfloatの範囲が1.2 * 10^-38であるのでしょうか?

私は10^-38まで保存することはできませんが、floatの変数は10^-6まで保存できますか?

+2

これはx64で期待されています。なぜあなたは二倍で十分ではないと感じますか?浮動小数点がどのように動作するかは理解できませんが、コメントで判断してください。あなたはそれを続行する前に置く必要があります。値は仮数と指数として格納されていることを知る必要があります。 –

+0

あなたはそれをあまりにも過度に思っています。もしあなたが 'long double'精度で戦っているなら、代わりに別のアプローチを使うべきです。また、 ''%.20Lf "'で 'long double'を表示してください。 – DeiDei

+1

'z'を'%Lf'でフォーマットしなければなりません(ただし、 'sizeof(double)== sizeof(long double)'ならばそれを使うことになります)。 –

答えて

5

まず、long doubleの値を%Lfと印刷する必要があります。

long double変数にdoubleとして表現できない値を含める場合は、doubleという定数で初期化しないでください。 3.14159264351134890172のタイプがdoubleで、コンパイラでFLT_EVAL_METHODが0または1に定義されている場合、long double z = 3.14159264351134890172;を使用するとlong doubleの値がdoubleの値に設定されます。zは、代わりに、行は次のようになります

long double z = 3.14159264351134890172L; 

あなたの質問への短い答えを「float値の範囲について1.2E-38である3.4E + 38に...」の後にあなたのマシン上の浮動小数点フォーマットがベースになっていることです2であり、表現可能な値は基数10で表現されているものと同じではないことを示しています。プラットフォーム上のタイプfloatは正確に24 バイナリ桁の精度を提供します。 doubleタイプは53を提供し、long doubleは64を提供すると期待できるはずです。長い答えはStackOverflowフォーマットでは長すぎますが、http://floating-point-gui.deから始めることもできます。

1

値はOPの調査に答えるために存在し、直接どのように似てdoublelong doubleを識別するために印刷することができます。それらはとまったく同じになります。

プリント***_MANT_DIG

浮動小数点の仮数における塩基FLT_RADIX桁数、p
C11§5.2.4.2.211

、種々の浮動小数点型の精度を見つけるために
#include <float.h> 
printf("FLT_RADIX   %d\n", FLT_RADIX); // Almost always 2 
printf("DBL_MANT_DIG  %d\n", DBL_MANT_DIG); 
printf("LDBL_MANT_DIG  %d\n", LDBL_MANT_DIG); 

FP正確な値に一致する10桁の桁数を確認するには、***_DIG(往復「text-FP-text」を予想される)

printf("DBL_DIG   %d\n", DBL_DIG); 
printf("LDBL_DIG   %d\n", LDBL_DIG); 

予想通り***_DECIMAL_DIG(ラウンドトリップする "FP-テキスト-FP" を使用し、多くの小数点以下の桁数がFP正確な値は多分影響することを印刷する方法を見つけるために)

printf("DBL_DECIMAL_DIG %d\n", DBL_DECIMAL_DIG); 
printf("LDBL_DECIMAL_DIG %d\n", LDBL_DECIMAL_DIG); 

double d = 3; 
long double ld = 3; 
printf("(double) 1/3  %.*e %.*e\n", DBL_DIG - 1, 1/d, 
    DBL_DECIMAL_DIG - 1, 1/d); 
printf("(long double) 1/3 %.*Le %.*Le\n", LDBL_DIG - 1, 1/ld, 
    LDBL_DECIMAL_DIG - 1, 1/ld); 

出力例

FLT_RADIX   2 
DBL_MANT_DIG  53 
LDBL_MANT_DIG  64 
DBL_DIG   15 
LDBL_DIG   18 
DBL_DECIMAL_DIG 17 
LDBL_DECIMAL_DIG 21 
(double) 1/3  3.33333333333333e-01 3.3333333333333331e-01 
(long double) 1/3 3.33333333333333333e-01 3.33333333333333333342e-01 

注:範囲の問題については
、印刷***_MAX, ***_MIN
long doubleの印刷指定でLを必ず使用してください。

関連する問題