浮動小数点数と機械精度

2811 ワード

コードを最適化する過程で再びデータのボトルネックである精度の問題に遭遇し、このよく知っているテーマ:浮動小数点数と精度を復習せざるを得ない.
なぜ単純な整数で、コンピュータ内の値が一致しないのですか?例えば、実際の数値は558783388であり、floatでは558783360であり、
log2( 558783388)

ans =

   29.0577
log2( 558783360)

ans =

   29.0577
doubleでは5.58833745970526 e+08で、doubleの精度はfloatより高いため、実際の数値に近い
エラー
これはすべてバイナリのためで、バイナリで1つの数(10進数)を表し、誤差があります.もう1つの例を挙げます.
double a=0.2;
メモリには、aに対応するメモリ領域データが表示されます.
9A 99 99 99 99 99 C9 3F
これはリトルエンドストレージ方式で、上位に置き換えられます.
3F C9 99 99 99 99 99 9A

doubleのメモリの形式は次のとおりです(詳細はIEEE 754浮動小数点演算基準を参照).
63(1 bits) 62~52(11 bits)  51~0(52 bits)
             (  )       
             (-1022~1023)

可視シンボルビットは0であり、指数ビットは0 x 3 FC、すなわち1020であり、2^10−1、すなわち1023を減算し、得られる指数は−3である.端数は99999999999999 Aです.だから完全な数字は16進数の1.99999999999999 Aに2^-3を乗じて、得ます
a=0.2000 0000 0000 0000 1110 2230 2462 5157
では、0.2をdoubleで表す場合の誤差が見られます.この例は、任意の実数aを有限ワード長のバイナリ浮動小数点数で表す場合に誤差が導入される可能性があることを示す.実数aの指数をeとし,末尾数をnとし,明らかに誤差<(1/2^n)*2^e
せいど
機械の精度を条件を満たすように定義することができます.
float(1+ε)>1

の最小浮動小数点数ε.明らかにdoubleの機械精度は1/2^52です.floatの機械精度は1/2^23です.上の例では、10進数の0.2の後ろの17位から誤差があります.すなわち、10^-16です.
10^-16

ans =

   1.0000e-16
 2^-52

ans =

   2.2204e-16
double現在では精度を決定するのに十分ではありません.最小値は次のとおりです.
10^-15

ans =

   1.0000e-15
は小数位で、より科学的な説は有効な数字です.小数点前のデフォルトには1があるため、floatの有効数字は24 bitで、8ビット10進数の有効数字に対応しています.doubleの有効数字は53 bitで、16ビットの10進数に対応しています.つまり、1つの実数の有効数字が8桁を超えて、単精度浮動小数点数で表すと、誤差が発生します!同様に、実数の有効数字が16ビットを超えると、二重精度浮動小数点数で表すと誤差も発生します!
NaNとINF
matlabではよく遭遇し,計算後の行列にはこの2つの記号が存在する.特殊な浮動小数点数に属します.ステップコードが0または全1になると、特殊な浮動小数点数が表示されます.
#指数が全0の場合、末尾数が0の場合、記号ビットによって+0と-0に分けることができます.端数が0以外の場合、端数部は小数点前の1が存在するとは仮定しません.あるいはこれらの数は0に近すぎる.指数はもう小さくならないからだ.たとえば、メモリ内のdouble変数の表示(16進数):
00 00 00 00 00 00 00 01
次符号は0であり、指数は-1022に直接等しく、末尾数は1/2^52であるため、結果は:
4.9406564584124654e-324

#
指数が全1の場合、端数が0の場合、無限を表し、符号ビットに基づいて+INF、-INFと決定される.端数が0でない場合はNaN非数値を表す
浮動小数点数の特殊値(double)をまとめた表
                     
0         0        0      +0
1         0        0      -0
0         2047     0      +∞
1         2047     0      -∞
0         2047      0    NaN

まとめ
floatもintも32 bitですが、floatの末尾数は23 bitしか使いません.intの精度はfloatより高く,floatの表現範囲はintより大きい.floatは精度を犠牲にしてより大きな表現範囲を取り替えた.doubleの末尾数は52 bitで32 bitのintより高いので、dobuleでintを表すと精度損失はありません.doubleは科学計算の一般的なタイプで、doubleの内在と制限を理解し、よりよく使用するのに役立ちます.