それでも誰かがこのページに到達した場合、浮動小数点の減算によってエラーまたは奇妙な値が発生するという同様の問題が発生します。この問題についてもう少し詳しく説明したいと思います。原因は浮動小数点数です。問題を説明するために、簡単な例でその理由を説明し、そこから、なぜそれが丸めなどに影響を与えるのかを推測できます。
PHPとは直接関係がなく、バグでもありません。ただし、すべてのプログラマーはこの問題に注意する必要があります。
この問題は、20年前にも多くの命を奪いました。
1991年2月25日、MIM-104パトリオットミサイルバッテリーの浮動数計算におけるこの問題により、サウジアラビアのダーランで入ってくるスカッドミサイルを迎撃できなくなり、米軍の第14クォーターマスターデタッチメントから28人の兵士が死亡しました。
しかし、なぜそれが起こるのでしょうか?
その理由は、浮動小数点値は限られた精度を表すためです。そのため、処理後の値の文字列表現が同じにならない場合があります。また、スクリプトに浮動小数点値を記述し、数学演算なしで直接印刷することも含まれます。
簡単な例:
$a = '36';
$b = '-35.99';
echo ($a + $b);
あなたはそれが0.01を印刷することを期待するでしょう?しかし、0.009999999999998のような非常に奇妙な答えが出力されます
他の数値と同様に、浮動小数点数doubleまたはfloatは、0と1の文字列としてメモリに格納されます。浮動小数点が整数とどのように異なるかは、0と1を調べたいときにそれらをどのように解釈するかという点にあります。それらがどのように保存されるかについては多くの基準があります。
浮動小数点数は通常、左から右に、符号ビット、指数フィールド、および仮数または仮数としてコンピューターデータにパックされます。
十分なスペースがないため、10進数は2進数で適切に表されません。だから、uouは0.3333333のように1/3を正確に表現することはできません...そうですか?0.01を2進浮動小数点数として表現できないのも同じ理由です。1/100は0.00000010100011110101110000.....で、10100011110101110000が繰り返されます。
0.01を簡略化してシステムで切り捨てた形式の01000111101011100001010を2進数で保持すると、10進数に変換すると、0.0099999のように読み取られます。システムによっては...(64ビットコンピューターの方が32ビットよりもはるかに高い精度が得られます) )。この場合、オペレーティングシステムは、表示どおりに印刷するか、より人間が読める形式で印刷するかを決定します。したがって、それをどのように表現したいかはマシンに依存します。ただし、さまざまな方法で言語レベルで保護できます。
結果をフォーマットする場合は、echo number_format(0.009999999999998、2); 0.01を出力します。
これは、この場合、どのように読み取るか、どの程度の精度が必要かを指示するためです。参照:1、2、3、4、5 _ _ _ _ _ _ _