495

倍精度と単精度の違いについて読みました。ただし、ほとんどの場合、floatdoubleは互換性があるようです。つまり、どちらを使用しても結果には影響しないようです。これは本当にそうですか?float と double はいつ交換できますか? それらの違いは何ですか?

4

14 に答える 14

604

大きな違い。

名前が示すように、 adoubleの精度は[1]の 2 倍です。一般に、aの精度は 10 進数で 15 桁ですが、7 桁です。floatdoublefloat

桁数の計算方法は次のとおりです。

double52 仮数ビット + 1 隠しビット: log(2 53 )÷log(10) = 15.95 桁

float23 仮数ビット + 1 隠しビット: log(2 24 )÷log(10) = 7.22 桁

この精度の低下により、繰り返し計算が行われると、より大きな切り捨て誤差が蓄積される可能性があります。

float a = 1.f / 81;
float b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.7g\n", b); // prints 9.000023

その間

double a = 1.0 / 81;
double b = 0;
for (int i = 0; i < 729; ++ i)
    b += a;
printf("%.15g\n", b); // prints 8.99999999999996

また、float の最大値は about3e38ですが、double は about です1.7e308。したがって、60 の階乗を計算するなど、単純なものfloatよりもはるかに簡単に "無限大" (つまり、特殊な浮動小数点数)を使用できます。double

テスト中、少数のテスト ケースにこれらの膨大な数が含まれている可能性があり、float を使用するとプログラムが失敗する可能性があります。


もちろん、double十分に正確ではない場合もあるため、long double[1]がある場合もあります(上記の例では、Mac では 9.000000000000000066 が返されます)。ただし、すべての浮動小数点型は丸め誤差の影響を受けるため、精度が非常に重要な場合 (例: お金)処理)intまたは分数クラスを使用する必要があります。


+=さらに、エラーがすぐに蓄積されるため、多くの浮動小数点数を合計するために使用しないでください。Python を使用している場合は、fsum. それ以外の場合は、カハン総和アルゴリズムの実装を試みてください。


float[1]: C および C++ 標準では、 、doubleおよびの表現が指定されていませんlong double。3 つすべてが IEEE 倍精度として実装される可能性があります。それにもかかわらず、ほとんどのアーキテクチャ (gcc、MSVC; x86、x64、ARM) では、float 実際には IEEE 単精度浮動小数点数 (binary32) でありdouble IEEE 倍精度浮動小数点数 (binary64) です。

于 2010-03-05T13:06:43.593 に答える
30

2次方程式x 2  − 4.0000000  x  + 3.9999999 = 0 を考えると、有効桁数 10 の正確な根はr 1  = 2.000316228 およびr 2  = 1.999683772 です。

floatとを使用しdoubleて、テスト プログラムを作成できます。

#include <stdio.h>
#include <math.h>

void dbl_solve(double a, double b, double c)
{
    double d = b*b - 4.0*a*c;
    double sd = sqrt(d);
    double r1 = (-b + sd) / (2.0*a);
    double r2 = (-b - sd) / (2.0*a);
    printf("%.5f\t%.5f\n", r1, r2);
}

void flt_solve(float a, float b, float c)
{
    float d = b*b - 4.0f*a*c;
    float sd = sqrtf(d);
    float r1 = (-b + sd) / (2.0f*a);
    float r2 = (-b - sd) / (2.0f*a);
    printf("%.5f\t%.5f\n", r1, r2);
}   

int main(void)
{
    float fa = 1.0f;
    float fb = -4.0000000f;
    float fc = 3.9999999f;
    double da = 1.0;
    double db = -4.0000000;
    double dc = 3.9999999;
    flt_solve(fa, fb, fc);
    dbl_solve(da, db, dc);
    return 0;
}  

プログラムを実行すると、次のようになります。

2.00000 2.00000
2.00032 1.99968

数値は大きくありませんが、 を使用するとキャンセル効果が得られることに注意してくださいfloat

(実際、上記は単精度または倍精度の浮動小数点数を使用して二次方程式を解く最良の方法ではありませんが、より安定した方法を使用しても答えは変わりません。)

于 2010-03-05T17:57:25.627 に答える
19
  • double は 64 で、単精度 (float) は 32 ビットです。
  • double の仮数部 (実数の整数ビット) が大きくなります。
  • 不正確さは double の方が小さくなります。
于 2010-03-05T12:53:20.800 に答える
13

エラーが発生したため、理解するのに永遠に時間がかかり、浮動小数点数の精度の良い例が得られる可能性があります。

#include <iostream>
#include <iomanip>

int main(){
  for(float t=0;t<1;t+=0.01){
     std::cout << std::fixed << std::setprecision(6) << t << std::endl;
  }
}

出力は

0.000000
0.010000
0.020000
0.030000
0.040000
0.050000
0.060000
0.070000
0.080000
0.090000
0.100000
0.110000
0.120000
0.130000
0.140000
0.150000
0.160000
0.170000
0.180000
0.190000
0.200000
0.210000
0.220000
0.230000
0.240000
0.250000
0.260000
0.270000
0.280000
0.290000
0.300000
0.310000
0.320000
0.330000
0.340000
0.350000
0.360000
0.370000
0.380000
0.390000
0.400000
0.410000
0.420000
0.430000
0.440000
0.450000
0.460000
0.470000
0.480000
0.490000
0.500000
0.510000
0.520000
0.530000
0.540000
0.550000
0.560000
0.570000
0.580000
0.590000
0.600000
0.610000
0.620000
0.630000
0.640000
0.650000
0.660000
0.670000
0.680000
0.690000
0.700000
0.710000
0.720000
0.730000
0.740000
0.750000
0.760000
0.770000
0.780000
0.790000
0.800000
0.810000
0.820000
0.830000
0.839999
0.849999
0.859999
0.869999
0.879999
0.889999
0.899999
0.909999
0.919999
0.929999
0.939999
0.949999
0.959999
0.969999
0.979999
0.989999
0.999999

0.83 以降でわかるように、精度が大幅に低下します。

tしかし、ダブルに設定すれば、そのような問題は発生しません。

この小さなエラーに気付くのに 5 時間もかかり、プログラムが台無しになりました。

于 2015-10-20T06:51:04.713 に答える
12

浮動小数点計算に含まれる数値のサイズは、最も重要なことではありません。関連するのは、実行されている計算です。

本質的に、計算を実行していて、結果が無理数または循環小数である場合、その数値が使用している有限サイズのデータ​​構造に押しつぶされると、丸め誤差が発生します。double は float の 2 倍のサイズであるため、丸め誤差ははるかに小さくなります。

テストでは、この種のエラーの原因となる数値を具体的に使用する場合があるため、コードで適切な型を使用したことをテストしました。

于 2010-03-05T13:05:56.283 に答える
10

float 型、長さ 32 ビット、精度は 7 桁です。非常に大きな範囲または非常に小さな範囲 (+/- 3.4 * 10^38 または * 10^-38) の値を格納できますが、有効桁数は 7 桁のみです。

double 型、長さ 64 ビット、範囲が広く (*10^+/-308)、精度が 15 桁です。

long double 型は名目上 80 ビットですが、指定されたコンパイラ/OS のペアリングでは、アラインメントのために 12 ~ 16 バイトとして格納される場合があります。long double の指数は途方もなく大きく、19 桁の精度を持つ必要があります。Microsoft は、その無限の知恵により、long double をプレーンな double と同じ 8 バイトに制限しています。

一般的に言えば、浮動小数点値/変数が必要な場合は double 型を使用してください。式で使用されるリテラル浮動小数点値はデフォルトで double として扱われ、浮動小数点値を返すほとんどの数学関数は double を返します。double を使用するだけで、多くの頭痛の種や型キャストを回避できます。

于 2011-03-08T05:13:27.817 に答える
3

組み込みの比較演算は、2 つの数値を浮動小数点で比較する場合とは異なります。データ型 (float または double) の違いにより、結果が異なる場合があります。

于 2011-12-07T07:40:27.383 に答える
3

浮動小数点数を使用する場合、ローカルのテストがサーバー側で行われるテストとまったく同じになるとは思えません。環境とコンパイラは、ローカル システムと最終テストが実行される場所で異なる可能性があります。特に2つの浮動小数点数を比較しようとする場合、いくつかのTopCoderコンテストでこの問題を何度も見てきました。

于 2010-03-05T13:00:57.617 に答える