PHPで簡単な計算をしています。
(2.70 + 2.30 + 29.70 + -2.30 + -29.70 + -2.70)
- データベースからこれらの数値を取得
PHPは8.8817841970013E-016
ゼロではなく答えとして与えています。
round、number_format などの関数を試しましたが、それでも同じ結果が得られます
PHPで簡単な計算をしています。
(2.70 + 2.30 + 29.70 + -2.30 + -29.70 + -2.70)
- データベースからこれらの数値を取得
PHPは8.8817841970013E-016
ゼロではなく答えとして与えています。
round、number_format などの関数を試しましたが、それでも同じ結果が得られます
浮動小数点演算は、いくつかの数値で不正確さを生み出す可能性があります。
これらのエラーがない(通貨ですか?)このような算術演算を実行する場合は、整数として実行し、最後に100で除算してみてください。
php > echo (270 + 230 + 2970 + -230 + -2970 + -270)/100;
0
それが実際に通貨である場合は、それらをデータベースのように保存しDECIMAL
、データベースに計算を任せます。
また、正常にround
動作するはずです:
php > echo 2.70 + 2.30 + 29.70 + -2.30 + -29.70 + -2.70;
6.2172489379009E-15
php > echo round(2.70 + 2.30 + 29.70 + -2.30 + -29.70 + -2.70);
0
PHPのドキュメントサイトから、詳細が記載されたページも見つかりました。
式の10進表現は「0.00000000000000088817841970013」です。これは0に非常に近い値であり、コンピューターで浮動小数点数を使用して計算する場合の標準的な問題のために存在します。
これがなぜであるかを深く掘り下げたい場合は、http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlにすばらしい記事があります(ただし、非常に深いので注意してください:) )。
これを試して
round(2.70 + 2.30 + 29.70 - 2.30 - 29.70 - 2.70)
質問の数字の見え方から、小数点以下2桁の小数の正確な扱いが重要なケースかもしれません。その場合は、100 分の 1 単位で作業することを検討してください。たとえば、米国の通貨は、小数点以下 2 桁のドルではなく、セントの整数として扱うことができます。
通常の数値解析を引き続き使用できますが、数値を取得したらすぐに 100 を掛けて、最も近い整数に丸めます。同様に、出力では 100 で除算し、小数点以下 2 桁にフォーマットします。整数値に対して中間計算を行います。
What Every Computer Scientist Should Know About Floating-Point Arithmeticを読むことをお勧めします