epsilon
まず、の戻り値に実際に含まれているものを確認しましょうsys.float_info
。
イプシロン(または) は、 0.5 + ≠ 0.5 AND 0.5 - ≠ 0.5
となる最小の数です。
0.5
Python は、繰り返しインクリメントまたはデクリメントを引き起こす最小の数値はepsilon=2.220446049250313e-16
--であると言っていますが、これは値 0.5 のみです。をインクリメントしようとしてい1.0
ます1.0e-17
。これは、0.5 の場合 (1.0e-17 と 2.2e-16) よりも小さい数値でインクリメントされる大きな値 (1.0 対 0.5) です。1.0e-17 の増分値は 1.0 の相対イプシロンよりも 1 桁小さいため、おおよそ 1 桁ずれています。
これはここで見ることができます:
これらはの値を変更します0.5
>>> 0.5+sys.float_info.epsilon
0.5000000000000002
>>> 0.5-sys.float_info.epsilon
0.4999999999999998
これらの値は次のことを行いません。
>>> 0.5+sys.float_info.epsilon/10.0
0.5
>>> 0.5-sys.float_info.epsilon/10.0
0.5
>>> 5.0+sys.float_info.epsilon
5.0
>>> 5.0-sys.float_info.epsilon
5.0
説明:
IEEE 754は、ほとんどの標準的なコンピューターで現在使用されている浮動小数点形式を定義します (特殊なコンピューターやライブラリは別の形式を使用する場合があります)。IEEE 754 の64 ビット形式は、53 ビットの精度を使用して計算し、52 ビットを浮動小数点数の仮数に格納します。ポイント値。使用する固定の 52/53 ビットがあるため、仮数の大きさと精度は値が大きい/小さい場合に変化します。そのため、浮動小数点数の相対的な大きさが変化すると変化します。0.5 の値は、1.0 および 100.0 の値とは異なります。
さまざまな非常に優れたプラットフォーム固有の理由 (ストレージと表現、丸めなど) により、より小さな数値を使用することもできますが、epsilon は 64 ビット浮動小数点形式に対して 52 ビットの精度を使用するように定義されています。ほとんどの Python 実装では float に C の double float を使用するため、これを実証できます。
>>> 2**-52==sys.float_info.epsilon
True
プラットフォームが何ビットを実行するかを確認します。
>>> 0.5 + 2.0**-53
0.5000000000000001
>>> 0.5 - 2.0**-53
0.4999999999999999
>>> 0.5 + 2.0**-54
0.5 # fail for 0.5 + 54 bits...
>>> 0.5 - 2.0**-54
0.49999999999999994 # OK for minus
>>> 0.5 - 2.0**-55
0.5 # fail for 0.5 minus 55 bits...
この問題にはいくつかの回避策があります。
- nextafterの C99 の概念を使用して、適切なイプシロンの値を計算できます。Python の場合、numpy または Decimal クラスを使用して を計算します
nextafter
。nextafter
私の以前の回答の詳細はこちら
- 整数を使用します。64 ビット整数は、丸めなしで 17 桁のイプシロン値を明確に処理します。
- 任意精度の数学ライブラリを使用します。Decimalは、標準の Python ディストリビューションに含まれています。
重要な概念は、 の値が値に対して相対的であるということです(また、インクリメントまたはデクリメントしている場合)。
これはここで見ることができます:
>>> numpy.nextafter(0.0,1.0)-0.0
4.9406564584124654e-324 # a relative epsilon value of 4.94e-324
>>> numpy.nextafter(0.01,1.0)-0.01
1.7347234759768071e-18 # 1e-17 would still work...
>>> numpy.nextafter(0.1,1.0)-0.1
1.3877787807814457e-17 # 1e-17 would >>barely<< work...
>>> numpy.nextafter(0.5,1.0)-0.5
1.1102230246251565e-16 # a relative epsilon value of 1.1e-16
>>> numpy.nextafter(500.0,501.0)-500.0
5.6843418860808015e-14 # relative epsilon of 5.6e-14
>>> numpy.nextafter(1e17,1e18)-1e17
16.0 # the other end of the spectrum...
したがって、1e-17 は 0.0 から 0.1 の間の値をインクリメントするのに便利に機能しますが、それより大きな値は多くないことがわかります。上記のように、1e17 の相対値は 16 です。