PHP - 浮動小数点数

浮動小数点数

浮動小数点数 (float, double, 実数) は、次の構文により指定できます。

<?php
  $a = 1.234; 
  $b = 1.2e3; 
  $c = 7E-10;
  $d = 1_234.567; // PHP 7.4.0 以降
?>
浮動小数点リテラル

浮動小数点の最大値は 64 ビットのシステムでは 1.7976931348623E+308 になります。PHP 7.2.0 以降では、浮動小数点の最大値は定数 PHP_FLOAT_MAX で、浮動小数点の最小値は定数 PHP_FLOAT_MIN で表せます。

ただし、浮動小数点数の精度には注意が必要です。PHP は通常 IEEE 754 倍精度フォーマットを使います。この形式は、1.11e-16 のオーダでの丸め処理で誤差が発生します。さらに、十進数では正確な小数で表せる有理数 (例えば 0.1 や 0.7) は、 二進数の浮動小数点数としては正確に表現できません。以下の計算結果では 8 を期待しますが、 7 が返されます。

<?php
  echo floor(( 0.1 + 0.7 ) * 10); // 7
?>
浮動小数点数の精度と誤差

これは、内部的な値が 7.9999999999999991118... のようになっているため、7 が返されます。そのため、より高い精度が必要な場合には任意精度数学関数、または gmp 関数を代わりに使用してください。

浮動小数点数値が等しいかどうかを比較するのには問題があります。これは、浮動小数点数値の内部表現形式に起因するものです。しかし、この制限を回避して浮動小数点数値の値を比較する方法もあります。

浮動小数点数値が等しいかどうかを調べるには、比較時の丸め誤差の上界を用います。この値は計算機イプシロン、あるいは丸め単位と呼ばれ、 計算時に扱える最小の差分を表します。$a$b は、精度 5 桁では等しくなります。

<?php
  $a = 1.23456789;
  $b = 1.23456780;
  $epsilon = 0.00001;

  if(abs($a - $b) < $epsilon) {
      echo "true";
  }
?>
float の比較

数値演算の結果が、定数 NaN で表される値になることがあります。この定数は、浮動小数点演算における未定義の値あるいは表現不能な値を表します。この値を他の値と比較すると、緩やかな比較および厳密な比較のいずれでも結果は FALSE になります。自分自身と比較した場合も含みますが、TRUE と比較した場合は除きます。

NaN はさまざまな値の数を表すものなので、NaN を他の値を比較してはいけません。チェックをする場合には、is_nan() を使います。

<?php
    var_dump(NAN || FALSE);  // bool(true)
    var_dump(NAN && TRUE);   // bool(true)
    var_dump(NAN === FALSE); // bool(false)
    var_dump(NAN === TRUE);  // bool(false)
    var_dump(NAN == FALSE);  // bool(false)
    var_dump(NAN == TRUE);   // bool(true)
    var_dump(NAN === NAN);   // bool(false)
    var_dump(NAN == NAN);    // bool(false)
    var_dump(NAN === "");    // bool(false)
    
    var_dump(is_nan(NAN));   // bool(true)
?>
NaN の比較

関連記事