てきとうなメモ

本の感想とか技術メモとか

文字列の数値化

$a = '9223372036854775807';
$b = '9223372036854775808';
if ($a == $b) {
    echo "$a == $b\n";
}
else {
    echo "$a != $b\n";
}
// displays 9223372036854775807 == 9223372036854775808

マニュアルを見ると

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.

PHP: Comparison Operators - Manual

数値っぽい文字列(numerical string)を含む比較は数値に変換してから比較することになっている。

When a string is evaluated in a numeric context, the resulting value and type are determined as follows.

If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an 'e' or 'E' followed by one or more digits.

PHP: Strings - Manual

で、文字列→数値変換では、PHP_INT_MAXを超えるとfloatになる。

ので、floatに変換されて同じ値になる、ということか。これを文字列として比較したい場合は"==="演算子を使わなければならない。

さらに、数値っぽい文字列(Zend/zend_operators.hのis_numeric_string)は16進数や指数表記も使えるので

$ php -r 'var_dump("0xFF" == "255");'
bool(true)
$ php -r 'var_dump("1e2" == "100");'
bool(true)

というようになる。