はじめに
前回はCodilityのコーディングテストを受けるときのポイントをまとめましたが、今回は注意点をまとめていきたいと思います。
コーディングテストでは単純なアルゴリズムだけでなく、データ型の特性に起因するエッジケースも問われる可能性があります。特に 浮動小数点数の精度やオーバーフローに注意を払わないと思わぬバグの原因になることがあります。
PHPの数値型について
PHPには主に2つの数値型があります。
-
int型:整数値(32ビット環境では -2,147,483,648 ~ 2,147,483,647、64ビット環境では -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)
-
float型:浮動小数点数(IEEE 754規格の倍精度浮動小数点数を使用)
浮動小数点の精度誤差
PHPのfloatは64ビットの倍精度浮動小数点数を使用しており、すべての小数を正確に表現できるわけではありません。
例えば、0.1 + 0.2
が0.3
にならないケースが発生します。
$a = 0.1;
$b = 0.2;
if ($a + $b == 0.3) {
echo "True";
} else {
echo "False";
}
// 出力: False
回避策
bcadd()
やbcmul()
などを使うことで、浮動小数点数の誤差を回避できます。
$a = "0.1";
$b = "0.2";
$result = bcadd($a, $b, 10); // 小数点以下10桁まで計算
echo $result; // 出力: 0.3000000000
整数型のオーバーフロー
PHPは整数型が64ビット環境では非常に大きな範囲を扱えますが、32ビット環境では比較的小さく、オーバーフローが発生しやすくなります。
$max = PHP_INT_MAX; // 環境依存で最大値を取得
var_dump($max); // 64ビット環境では 9223372036854775807
$result = $max + 1;
var_dump($result); // floatに変換される
整数が
PHP_INT_MAX
を超えると自動的にfloat
に変換され、精度が落ちます。
回避策
gmp_*
系関数を使うことで、大きな整数を扱うことができます。
$a = gmp_init(PHP_INT_MAX);
$b = gmp_add($a, 1);
echo gmp_strval($b); // 正確な計算が可能
無限大とNaN(Not a Number)
非常に大きな計算や定義できない数値操作を行うと、INF(無限大)
や NAN(非数)
となります。
var_dump(1.0e308 * 10); // INF
var_dump(acos(2)); // NAN
回避策
PHPでは is_infinite()
や is_nan()
を使用してチェックできます。
$result = 1.0e308 * 10;
if (is_infinite($result)) {
echo "無限大になっています";
}
数値変換時の注意点
PHPでは型変換が自動的に行われるため、不正な文字列を数値に変換すると予期しない挙動になります。
var_dump((int)"100abc"); // 100
var_dump((float)"1.2e3"); // 1200
var_dump((int)"abc"); // 0
回避策
型変換には filter_var()
を利用すると安全です。
$input = "100abc";
if (filter_var($input, FILTER_VALIDATE_INT) !== false) {
echo "整数です";
} else {
echo "整数ではありません";
}
まとめ
コーディング対策だけでなく、浮動小数展の精度誤差、オーバーフローなど気をつけていきましょう。
参考になれば幸いです