PHP の浮動小数点計算が不正確になるのはなぜですか?

PHPz
リリース: 2023-04-23 14:12:13
オリジナル
1715 人が閲覧しました

PHP プログラミングでは、不正確な浮動小数点計算の問題が発生することがあります。この問題の原因と解決策を理解すると、コードの信頼性と精度を向上させることができます。

1. 問題の原因

浮動小数点数は浮動小数点数を表現するのに非常に便利な方法ですが、いくつかの欠点もあります。主な理由は、コンピューターが数値の保存に 2 進数を使用しており、すべての浮動小数点数を正確に表現できないことです。これにより、丸め誤差が発生し、精度が失われます。

たとえば、単純な浮動小数点計算を想像してください:

0.1 + 0.2 = 0.3
ログイン後にコピー

PHP では、このコードの結果は次のようになります:

echo 0.1 + 0.2; //0.30000000000000004
ログイン後にコピー

明らかに、この結果は私たちが考えたものではありません。期待される 。これは、0.1 と 0.2 を 2 進数として正確に表すことができず、丸め誤差が発生するためです。この誤差は通常は小さいですが、精度の低下を引き起こしたり、一部の高精度の計算で誤差を引き起こすには十分です。

2. 解決策

不正確な浮動小数点計算の問題については、次の解決策を採用できます:

  1. 整数計算を使用する

正確な計算を実行する場合は、計算を実行する前に、浮動小数点数を整数に変換することができます。計算が完了すると、結果は浮動小数点数に変換されます。

たとえば、次の浮動小数点計算について考えてみましょう:

1.23 + 4.56 = 5.79
ログイン後にコピー

計算のために浮動小数点数を整数に変換できます:

$num1 = 123;
$num2 = 456;

$result = ($num1 + $num2) / 100; // 5.79
ログイン後にコピー
  1. BCMath の使用

PHP は、任意精度の数値を正確に計算するために使用できる BCMath 拡張機能を提供します。浮動小数点計算は、浮動小数点数の代わりに文字列を使用して数値を表す BCMath ライブラリを使用して実行できます。

たとえば、BCMath 関数ライブラリを使用して次の計算を行います。

$val1 = '0.1';
$val2 = '0.2';

echo bcadd($val1, $val2, 1); // 0.3
ログイン後にコピー

この例では、bcadd() 関数を使用して正確な浮動小数点加算を実行します。

  1. round() 関数を使用する

場合によっては、round() 関数を使用して精度誤差を減らすことができます。 Round() 関数は、浮動小数点数を指定された小数点以下の桁数に丸めます。

たとえば、次の計算について考えてみましょう:

$num1 = 0.1;
$num2 = 0.2;

$result = round($num1 + $num2, 1); // 0.3
ログイン後にコピー

この例では、round() 関数を使用して、結果を小数点第 1 位に四捨五入します。これによって精度誤差が完全に排除されるわけではありませんが、結果は予想されたものにかなり近づきます。

  1. 浮動小数点数の直接比較を避ける

浮動小数点数を比較する場合、何らかのフォールト トレランス メカニズムを使用する必要があります。浮動小数点数の精度は丸め誤差の影響を受ける可能性があるため、一般に 2 つの浮動小数点数の値を直接比較することは信頼できません。

たとえば、次の浮動小数点数の比較を考えてみましょう:

$val1 = 3.14159265;
$val2 = 3.14159267;

if ($val1 == $val2) {
  echo 'val1 等于 val2';
} else {
  echo 'val1 不等于 val2';
}
ログイン後にコピー

この例では、2 つの浮動小数点数を比較します。これら 2 つの数値は近いですが、等しくありません。したがって、コードは「val1 が val2 と等しくない」と出力します。

2 つの浮動小数点数を比較する必要がある場合は、許容値またはデルタ値を使用できます。許容値は、浮動小数点数の小さな誤差を許容できる小さな数値です。

たとえば、最大許容精度誤差を表すデルタ値を定義できます:

$delta = 0.00000001;
ログイン後にコピー

デルタ値を使用すると、次のコードを使用して浮動小数点数を比較できます:

$val1 = 3.14159265;
$val2 = 3.14159267;

if (abs($val1 - $val2) < $delta) {
  echo 'val1 等于 val2';
} else {
  echo 'val1 不等于 val2';
}
ログイン後にコピー

この例では、abs() 関数を使用して 2 つの浮動小数点数の差を計算し、それをデルタ値と比較します。 2 つの数値の差がデルタ値より小さい場合、それらは等しいとみなされます。

つまり、不正確な浮動小数点計算の問題はよくある問題です。 PHP では、この問題は、整数演算、BCMath 関数ライブラリ、round() 関数、デルタ値許容値などの方法を使用して解決できます。状況に応じて、さまざまな解決策を選択できます。

以上がPHP の浮動小数点計算が不正確になるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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