C言語やC#言語では、浮動小数点型のデータを単精度型(float)と倍精度型(double)を使って格納しており、Floatデータは32ビット、doubleデータは64ビットを占有します。変数 float f= 2.25f の場合、メモリはどのように割り当てられますか?ランダムに割り当てられたら世界は大混乱になるのではないでしょうか? 実際、記憶方式に関しては、float と double はどちらも IEEE の仕様に準拠しており、double は R64.53 に準拠しています。
単精度であろうと倍精度であろうと、ストレージは 3 つの部分に分割されます: 符号ビット (Sign): 0 は正を表し、1 は負を表します 指数ビット (Exponent): 科学的表記法の指数データを格納するために使用されます。シフトストレージを使用しますMantissa (Mantissa): 仮数部この記事では、主に PHP 浮動小数点数の精度の問題について概要を紹介します。この記事では、3 つの異なる段落を使用して、PHP 浮動小数点数の精度損失の問題に焦点を当てます。この問題の原因と解決策は、困っている友人が参考にしてください1. PHP 浮動小数点精度損失問題
まず、次のコードを見てください:$f = 0.57; echo intval($f * 100); //56少し驚くかもしれませんが、PHP は IEEE 754 倍精度に従っています: 64 ビット倍精度の浮動小数点数は、1 つの符号ビット (E)、11 の指数ビット (Q)、および 52 の仮数 (M) で表されます。ビット (合計 64 ビット)。
符号ビット: 最上位ビットはデータの符号を示し、0 は正の数を示し、1 は負の数を示します。
指数ビット:データの累乗を基数2で表し、指数はオフセットコードで表されます。
仮数:データの小数点以下の有効桁を表します。
2. PHP 浮動小数点数の精度の問題
まずは質問を見てみましょう:コードは次のとおりです:
$f = 0.58; var_dump(intval($f * 100)); //为啥输出57このような疑問を持ったことがある学生は多いと思います。 具体的な原理については、「Brother Bird」の記事で詳しく説明されています: PHP 浮動小数点数の
FAQ への回答
それでは、この問題を回避するにはどうすればよいでしょうか?多くの方法がありますが、ここでは 2 つ説明します:
1. sprintf
コードは次のとおりです:
substr(sprintf("%.10f", ($a/ $b)), 0, -7);
2.round (四捨五入されることに注意してください)
コードは次のとおりです:
round($a/$b, 3);
または、より良い方法がある場合は、メッセージを残して教えてください。
3. PHP 浮動小数点数に関するよくある質問への答えPHP 浮動小数点数については、以前に次の記事を書きました: PHP の浮動小数点数についてはすべて「偽物」です
ただし、その部分で 1 つ見逃していました。これは、次の一般的な質問に対する答えです:
コードは次のとおりです:
<?php $f = 0.58; var_dump(intval($f * 100)); //为啥输出57 ?>
なぜ出力は 57 なのでしょうか? PHP のバグですか?
このような質問をしたことがある学生は多いと思います。なぜなら、bugs.php.net でよく質問する人は言うまでもなく、同様の質問をする人がたくさんいるからです...
この理由を理解するには、まず浮動小数点数 (IEEE 754) の表現を知る必要があります:
浮動小数点数は、長さが 64 ビット (倍精度) の場合、1 つの符号ビット (E)、11 の指数ビット (Q)、および 52 の仮数ビット (M) (合計 64 ビット) で表されます。 ).
符号ビット: 最上位ビットはデータの符号を表し、0 は正の数を表し、1 は負の数を表します。
指数ビット: データの累乗を基数 2 で表し、指数はオフセット コードで表されます。
仮数: データの小数点以下の有効桁を表します。
ここでの重要な点は、 2 進数での 10 進数の表現についてはどうですか? 2 進数で表現すると、Baidu で検索できます。ここでは詳しく説明しませんが、理解する必要があるのは、2 進数表現の場合、0.58 は無限に長い値であるということです。次の数値は暗黙の 1) を省略します。..
0.58 のバイナリ表現は基本的に (52 ビット): 0010100011110101110000101000111101011100001010001111 0.57 のバイナリ表現は基本的に (52 ビット): 101011100001010001111 0101110000101000111101
そして計算すると、この 2 つの 2 進数これらの 52 ビットのみを介して、次のことが可能です:
コードをコピーします
0.58 -> 0.57999999999999996 0.57 -> 0.569999999999999950.58 * 100 の具体的な浮動小数点乗算については、詳しくは考慮しません。 (浮動小数点)を見て、暗算で漠然と見てみると… 0.58 * 100 = 57.999999999
それを積分すると、当然57になります…
この問題の重要なポイントは、「一見有限に見える 10 進数は、コンピューターの 2 進数表現では実際には無限である」ということです。
以上がPHP 浮動小数点精度に関する質問の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。