0

24151.40 - 31891.10 = -7739.699999999997

これらの 2 つの数値を、タイプが decimal(14,2) 24151.40 31891.10 の MySQL テーブルから取得します。上記のとおりに保存され、PHP とまったく同じようにエコーされます。しかし、最初の値から 2 番目の値を引くと、-7,739.7 ではなく、-7739.699999999997 という数値が得られます。なぜ余分な精度? そして、それはどこから来ているのですか?

4

3 に答える 3

4

私が Authorize.Net のために書いた記事から:

1 足す 1 は 2 ですよね?.2 たす 1.4 かける 10 はどうですか? それは16に等しいですよね?PHP (または他のほとんどのプログラミング言語) で計算を行っている場合は、そうではありません。

echo floor((0.2 + 1.4) * 10); // Should be 16. But it's 15!

これは、浮動小数点数が内部でどのように処理されるかによるものです。これらは固定の小数点以下の桁数で表され、期待どおりに合計されない数値になる可能性があります。内部的には、.2 プラス 1.4 かける 10 の例は、およそ 15.9999999998 程度に計算されます。この種の計算は、パーセンテージのように正確である必要のない数値を扱う場合に適しています。しかし、お金を扱う場合、どこかで不足しているペニーまたはドルがすぐに追加され、不足しているお金が不足していることを好む人はいないため、精度が重要です。

BC数学ソリューション

幸いなことに、PHP はBC Math 拡張機能を提供します。これは、「任意精度の数学のために、PHP は、文字列として表される任意のサイズと精度の数値をサポートする Binary Calculator を提供します」。つまり、この拡張機能を使用して、金額を正確に計算できます。BC Math 拡張機能には足し算引き算掛け算割り算など、最も一般的な精度の演算を実行できる関数が含まれています。

より良い例

上記と同じ例ですが、bcadd() 関数を使用して計算を行っています。3 つのパラメーターが必要です。最初の 2 つは追加したい値で、3 番目は正確にしたい小数点以下の桁数です。お金を扱っているので、精度を小数点以下 2 桁に設定します。

echo floor(bcadd('0.2', '1.4', 2) * 10); // It's 16 like we would expect it to be.
于 2012-05-04T16:34:48.717 に答える
1

PHP には、MySQL のような 10 進数型はありません。浮動小数点数を使用します。フロートは不正確であることで有名です。

これを解決するには、以下を調べてくださいnumber_format

echo number_format(24151.40 - 31891.10, 2, '.', '');

より正確な数値操作については、PHP の数学拡張機能を参照することもできます。

http://www.php.net/manual/en/refs.math.php

于 2012-05-04T16:34:11.687 に答える
1

これは、科学的に 1.FRACTAL * 2^exponential power に関連する一般的な float/double 精度レートに関係しています。接頭辞 1 があるため、技術的にゼロなどというものはなく、取得できる 0 に最も近い値は 1.0 * 2 ^ -127 で、.000000[127 0s]00001 です。

回答を特定の精度で四捨五入することにより、丸め係数により、より正確な回答が得られます。

http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_round

于 2012-05-04T16:34:37.737 に答える