PHPの浮動小数点比較方法

WBOY
リリース: 2016-07-30 13:30:02
オリジナル
944 人が閲覧しました

浮動小数点演算の精度の問題

まず例を見てみましょう:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$a</span>+<span>$b</span>)==<span>$c</span>);
var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);
<span>?></span></span></code>
ログイン後にコピー

$a+$b==$cはtrueを返します、正しい
$c-$b== $a は false、エラー

を返します。なぜこれが起こっているのでしょうか?
演算後、精度が 20 桁の場合に実際に返される内容は次のとおりです:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

printf(<span>"%.20f"</span>, <span>$a</span>+<span>$b</span>); <span>// 1.00000000000000000000</span>
printf(<span>"%.20f"</span>, <span>$c</span>-<span>$b</span>); <span>// 0.09999999999999997780</span><span>?></span></span></code>
ログイン後にコピー

$c-$b は 0.09999999999999997780 であるため、0.1 と比較すると false が返されます

この問題は浮動小数点であるために発生します小数点計算には精度が伴いますが、浮動小数点数を 2 進数に変換すると精度が失われる可能性があります。

浮動小数点数変換方式

整数部は2​​で割った剰余方式を採用
小数部は2を掛けることで四捨五入されます

例: 数値8.5を2進数に変換します
整数部分は8です
8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0
1は2より小さいので、計算する必要はありません。整数8の2進数表現は1000

小数部分は0.5
です。 0.5x2 = 1.0
四捨五入後の小数部は0なので、これ以上計算する必要はありません
10 進数 0.5 の 2 進表現は 0.1

8.5 2 進表現は 1000.1 です

数値 0.9 の 2 進表現を計算します
0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.2x2=0.4
0.4x2=0.8
0.8x2=1.6
.... その後、ループが続きます。迎撃精度が N の場合、N 以降の数値は四捨五入されるため、精度が失われます。
上記の例では、バイナリに変換すると 0.9 の精度が失われ、比較時にエラーが発生します。

したがって、浮動小数点数が最後の桁まで正確であるとは決して信じないでください。また、2 つの浮動小数点数が等しいかどうかを比較しないでください。

浮動小数点数を正しく比較する方法

1. ラウンドメソッドを使用して処理して比較します
例:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);                   <span>// false</span>
var_dump(round((<span>$c</span>-<span>$b</span>),<span>1</span>)==round(<span>$a</span>,<span>1</span>)); <span>// true</span><span>?></span></span></code>
ログイン後にコピー

2. 高精度の計算方法を使用します
最初に計算を実行するときは、精度が失われないように高精度の計算方法を使用してください。

高精度演算の方法は以下の通りです:
bcadd は 2 つの高精度数値を加算します
bccomp は 2 つの高精度数値を比較し、-1,0,1 を返します
bcdiv は 2 つの高精度数値を除算します
bcmod は高精度の数値剰余を見つけます
bcmul は 2 つの高精度数値を乗算します
bcpow は高精度の数値の力を見つけます
bcpowmod は高精度の数値パワーと係数を見つけます
bcscale はデフォルトの小数点数を設定します。これは Linux bc の "scale=" に相当します
bcsqrt は高精度の数値の平方根を求めます
bcsub 2 つの高精度の数値を減算します

例:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);          <span>// false</span>
var_dump(bcsub(<span>$c</span>, <span>$b</span>, <span>1</span>)==<span>$a</span>); <span>// true</span><span>?></span></span></code>
ログイン後にコピー

著作権表示: この記事はブロガーによるオリジナル記事であり、ブロガーの許可なしに転載することはできません。

以上、PHPの浮動小数点数の比較方法を内容も含めて紹介しましたが、PHPチュートリアルに興味のある方の参考になれば幸いです。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート