numpy.finfo
のdocstringは現在、 eps
属性を次のように定義しています。
1.0 + eps!= 1.0のような表現可能な最小の正の数。 [...]
その定義は、少なくともIEEE754バイナリ形式の一般的なケースでは正しくありません。 たとえば、通常の丸めから偶数への丸めモードでのIEEE 754 binary64形式では、記述された定義は2**-53 + 2**-105
(約1.1102230246251568e-16
)の値を示します。これは少しです。 2**-52
の正しい値の半分以上(約2.220446049250313e-16
)。
In [36]: eps = 2**-53 + 2**-105
In [37]: eps
Out[37]: 1.1102230246251568e-16
In [38]: 1.0 + eps != 1.0
Out[38]: True
In [39]: 1.0 + np.nextafter(eps, -np.inf) != 1.0
Out[39]: False
In [40]: np.finfo(float).eps
Out[40]: 2.2204460492503131e-16
いくつかの可能な言い換え:
1.0 + epsが表現できるような最小の正の数。
または:
1.0と1.0より大きい表現可能な最小のフロートとの差。
または、 nextafter
で次のように定義することもできます。
np.nextafter(1.0, np.inf) - 1.0
の値。
比較のために、C99標準のセクション5.2.4.2.2、パラグラフ11は、さまざまな*_EPSILON
マクロ( DBL_EPSILON
、 FLT_EPSILON
、...)を次のように定義しています。
1と、指定された浮動小数点型で表現可能な1より大きい最小値との差b 1− p
epsneg
のdocstringも同様に正しくありません。
ああ、ソースを見ると、 eps
は、実際には1 + eps != eps
ような最小の2の累乗として計算されていることがわかります。 これは、 1.0
と次の表現可能なフロートアップの1.0
の違いと同じではありませんが、IEEE754と四捨五入の場合は偶然に一致します。モード。 したがって、上記の提案された言い換えは無効です。 おそらく次のようなものです:
1.0 + epsが表現できるような2の最小の累乗。
ましだろう? 技術的には、その2
は浮動小数点の基数に置き換える必要がありますが、それはおそらく不必要に衒学的です。 NumPyは現在、基数10または基数16のフロートをサポートしていますか?
[余談ですが、私はイプシロンのC99スタイルの定義を非常に好みます。これは、フォーマットのみを含み、浮動小数点加算のセマンティクスに依存しないためです。 特に、C99定義は現在有効な丸めモードに依存しませんが、 1 + eps != 1
定義は依存します。]
「関連項目」セクションのnp.spacing
およびnp.nextafter
へのポインタも潜在的に役立ちます。
ここで私たちはほぼ4年後ですが、これは修正されていません。 この問題を解決するには、 https://github.com/numpy/numpy/pull/14618で十分ではないと思います。
バグレポートを明確にするために、docstring内のepsの現在の定義は、np.finfoによって返されるepsの値から約2倍ずれています。 (以下に示す数値は、IEEE-754 64ビット浮動小数点標準を使用した実装用です。)つまり、
np.finfo(1.0).eps = 2 **-52 = 2.220446049250313e-16
ただし、docstringはepsを次のように定義します
「1.0+ eps!= 1.0のような表現可能な最小の正の数。」
1.0 + eps_min!= 1.0の定義を満たすepsの実際の値は次のとおりです。
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
これは、np.finfo(1.0).epsの現在価値のほぼ1/2です。 下位互換性を維持するために、おそらくnp.finfo(1.0).epsの値を変更したくないでしょうが、epsのdocstring定義は、計算されたものと一致するように修正する必要があります。 np.finfo(1.0)epsのソースコードはnumpy.MachArを使用しており、2以外のベースを許可するドキュメントを見ると、epsの最良の定義は、 @ mdickinsonが以前に提案した初期のオプションの1つだと思います。 また、説明に値の例を追加します。
「1.0と1.0より大きい表現可能な最小フロートの違い。(IEEE-754標準の64ビットバイナリフロートの場合、eps = 2 **-52≅2.22e-16)。」
epsnegのdocstringも同様に正しくありません。
私もこの不正確さに出くわしました。 これは修正する必要があります。
参考までに、Matlabはそのeps
(同じ値)を次のように文書化します:「1.0から次に大きい倍精度数、つまり2 ^ -52までの距離」。
現在の定義は正しくなく、丸めの問題のために混乱しています。 @gwhammett提案された定義は正しく、より説明的であり、PRがこの問題を解決することを奨励しています。
最も参考になるコメント
ここで私たちはほぼ4年後ですが、これは修正されていません。 この問題を解決するには、 https://github.com/numpy/numpy/pull/14618で十分ではないと思います。
バグレポートを明確にするために、docstring内のepsの現在の定義は、np.finfoによって返されるepsの値から約2倍ずれています。 (以下に示す数値は、IEEE-754 64ビット浮動小数点標準を使用した実装用です。)つまり、
np.finfo(1.0).eps = 2 **-52 = 2.220446049250313e-16
ただし、docstringはepsを次のように定義します
1.0 + eps_min!= 1.0の定義を満たすepsの実際の値は次のとおりです。
eps_min = 2 -53 + 2 -105 = 1.1102230246251568e-16
これは、np.finfo(1.0).epsの現在価値のほぼ1/2です。 下位互換性を維持するために、おそらくnp.finfo(1.0).epsの値を変更したくないでしょうが、epsのdocstring定義は、計算されたものと一致するように修正する必要があります。 np.finfo(1.0)epsのソースコードはnumpy.MachArを使用しており、2以外のベースを許可するドキュメントを見ると、epsの最良の定義は、 @ mdickinsonが以前に提案した初期のオプションの1つだと思います。 また、説明に値の例を追加します。
epsnegのdocstringも同様に正しくありません。