なぜ PHP は結果を(int) ((0.1+0.7)*10)
8 ではなく 7 に変換するのでしょうか? (float) 8
結果にキャストすると結果が7になることはわかってい(int)
ますか?なぜそれが起こるのですか?
2 に答える
それはすべてについてfloat
です。PHP: 浮動小数点数を参照してください。
警告 - 浮動小数点の精度
浮動小数点数の精度は限られています。システムにもよりますが、PHP は通常、IEEE 754 倍精度形式を使用します。これは、1.11e-16 のオーダーで丸められるため、相対誤差が最大になります。非初等算術演算はより大きな誤差を与える可能性があり、もちろん、いくつかの演算が複合されている場合は誤差の伝播を考慮する必要があります。
さらに、0.1 や 0.7 のように、基数 10 の浮動小数点数として正確に表現できる有理数は、仮数のサイズに関係なく、内部で使用される基数 2 の浮動小数点数として正確に表現できません。したがって、精度をわずかに低下させることなく、内部のバイナリ対応物に変換することはできません。これは紛らわしい結果につながる可能性があります。たとえば、floor((0.1+0.7)*10) は通常、予想される 8 ではなく 7 を返します。これは、内部表現が 7.9999999999999991118....
したがって、浮動小数点数の結果を最後の桁まで信頼したり、浮動小数点数を直接比較して等しいかどうかを確認したりしないでください。より高い精度が必要な場合は、任意精度の数学関数と gmp 関数を使用できます。
追加資料:
ハレーの答えは素晴らしいです。
必要な追加情報は、int にキャストすると、次の数値にどれほど近いかに関係なく、常に小数点以下が切り捨てられることです。したがって、(int) 7.999999999999 は 7 になります。
キャストするときに最も近いものを取得するために丸めるのが一般的です。たとえば、
(int) (x + 0.5)
浮動小数点や丸め、切り捨てなどを処理する関数はたくさんあります。それらを読んで、ニーズに合ったものを選択する必要があります。