この記事の内容は、PHP の小数精度のコード解析に関するもので、一定の参考値がありますので、困っている方は参考にしていただければ幸いです。
プロジェクトで小数点第 2 位に四捨五入するときに精度の問題が発生しました:
$num = 0.99; $num1 = round($num, 2);//0.98999999999999999 $num2 = floatval($num);//0.98999999999999999
現在の解決策:
sprintf("%.2f", round($money, 2));//会自动四舍五入 echo substr(sprintf("%.3f",$n), 0, -1);//不四舍五入
テスト結果:
var_dump(json_encode(round(0.99 ,2)));//0.98999999999999999 var_dump(round(0.99 ,2));//0.99 $f = 0.58; var_dump(intval($f * 100));//57
約 57問題を分析できます:
浮動小数点数の表現 (IEEE 754: IEEE 2 進浮動小数点演算標準):
64 ビット長 (倍精度) を単位とする浮動小数点数たとえば、 は、1 つの符号ビット (E)、11 の指数ビット (Q)、および 52 の仮数ビット (M) (合計 64 ビット) で表されます。
符号ビット: 最上位ビットは、の符号を示します。データ、0 は正の数を示し、1 は負の数を示します。
指数ビット: データの累乗を底 2 で表し、指数はオフセット コードで表されます。
仮数部: データの小数点以下の有効な桁を表します。
0.58 バイナリ表現の場合 たとえば、無限に長い値です:
0.58 のバイナリ表現は基本的に (52 ビット): 0010100011110101110000101000111101011100001010001111
0.57 のバイナリ表現 (52 ビット)基本的に:001000 111101011100001010001010101110000101000101010101010101010110
これら2つのビットでのみ計算されている場合、2つのバイナリ番号は次のとおりです。 ; 0.5699999999999999
したがって、0.58 * 100 の結果は次のようになります: 57.999999999、整数型に変換: 57
浮動小数点数のバイナリ表現については、次を参照してください。浮動小数点数
次と同様:
(0.1 + 0.7) == 0.8//false floor((0.1+0.7)*10)//7 //内部结果可能是:7.9999999999 //所以:不可能精确的用有限位数表达某些十进制分数 1/3=3.33333333333 //而3.333333333333333*3,却不是1
結論:
したがって、浮動小数点数の結果が最後の桁まで正確であるとは決して信じず、決して比較しないでください。 2 つの浮動小数点数が等しいかどうか。本当に高い精度が必要な場合は、任意精度の数学関数または gmp 関数を使用する必要があります。高精度関数の使用をお勧めします:高精度関数
bcp — 2 つの任意精度数値の除算を計算します
bcmod — 任意精度数値のモジュロ
bcpowmod — 任意の精度の数値を、指定された係数で減じた別の数値に上げます
#bcsqrt — 任意精度数値の平方根
function getBcRound($number, $precision = 0) { $precision = ($precision < 0) ? 0 : (int) $precision; if (strcmp(bcadd($number, '0', $precision), bcadd($number, '0', $precision+1)) == 0) { return bcadd($number, '0', $precision); } if (getBcPresion($number) - $precision > 1) { $number = getBcRound($number, $precision + 1); } $t = '0.' . str_repeat('0', $precision) . '5'; return $number < 0 ? bcsub($number, $t, $precision) : bcadd($number, $t, $precision); } function getBcPresion($number) { $dotPosition = strpos($number, '.'); if ($dotPosition === false) { return 0; } return strlen($number) - strpos($number, '.') - 1; } $money = getBcRound(0.99, 2);
おすすめ関連記事:
PHP での AES 暗号化ファイルの解析 (コード付き)phpのcurlにおけるpostモードとgetモードのリクエストコードPHP中間キーの内容解析について
以上がPHPの小数精度のコード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。