私が知っている宿題をしているときに、この興味深い質問を見つけました。47.36/1.6**2 == 18.5
しかし、次のコードを実行しようとすると、False(trueである必要があります)が表示されます。
印刷47.36/1.6**2 == 18.5
誰かが何が起こっているのか知っていますか?
あなたはおそらく18.49999999999のような答えを得ていますが、これは18.5と正確には等しくありません。
いつものように、これに関連するリファレンスは、すべてのコンピューター科学者が浮動小数点演算について知っておくべきことです。
>>> 47.36/1.6**2
18.499999999999996
浮動小数点演算:問題と制限に関するこのページを参照してください。
10進モジュール18.5
を使用して、丸めや「十分に近い」動作を使用せずに、これを正確に計算する方法は次のとおりです。
>>> from decimal import Decimal
>>> Decimal('47.36') / Decimal('1.6')**2 == Decimal('18.5')
True
>>> float(Decimal('47.36') / Decimal('1.6')**2) == 18.5
True
簡単な答え: IEEE 754 浮動小数点は、分母が 2 のべき乗でない分数 (1/4、1/16、1/256 など) を正確に表すことができません。まったく正確にはありません。
「等しい」を「特定のデルタ内」として定義することにより、浮動小数点数を比較します。次のように書くことができます。
def almost_equals(a, b, delta=0.0005):
return abs(a - b) <= delta
次に、「おそらく等しい」かどうかを次のようにテストします。
>>> almost_equals(47.36/1.6**2, 18.5)
True
2 つの float を比較するときに、正確に等しいかどうかをチェックすることは避けます。代わりに、差を取り、ゼロに近いと考える値よりも小さいかどうかを確認します。
(47.36/1.6**2 - 18.5) < 0.00000000001
になります
真実
他の人が言ったように:
>>> 47.36/1.6**2
18.499999999999996
しかし、私が知る限り、これは浮動小数点演算の問題によるものではありません。Decimal()
(after from decimal import Decimal
)でオペランドをラップして 10 進演算を使用してDecimal('18.49999999999999772404279952')
も、答えは得られます。
ここで間違った使い方をしている可能性がDecimal()
あり、私の結果にもある種の浮動小数点エラーがあります。ただし、私が正しければ、18.5
どのような種類の数学を使用しても、その式は と等しくありません。
編集: Greg がコメントで指摘しているように、ここでの私のアプローチの問題は、Decimal(1.6) が 1.6 の float 表現をそのままの不正確さで Decimal に変換することです。これは正しい答えを与えます:
>>> Decimal('47.36') / Decimal('1.6')**2
Decimal('18.5')
Kirk が提案するように、 fractionsモジュールを使用することをお勧めします。
47.36 / 1.6* 2は整数を返します。したがって、47.36 / 1.6 * 2は18になり、18.5と等しくなりません。
編集
申し訳ありませんが、実際には18.499999として保存されています。
あなたはこれをするべきです
import numpy as np
print np.around((47.36/1.6**2), decimals=1) == 18.5
これはTrueを返します。