Edited at

PHP_INT_MAXを超えた話

More than 1 year has passed since last update.


この記事を書こうと思った経緯

回復したキャラがなぜか死ぬ現象に悩まされていました。

原因を調べる中で、PHP_INT_MAXを超えてしまった場合の挙動について良い勉強になったので、記事として残しておこうと思いました。

※以下の挙動はPHP5.6になります。


PHP_INT_MAXを超えると何が起こるの?

PHP_INT_MAXは、64ビットのデフォルトだと9223372036854775807が最大値となります。

<?php 

var_dump(PHP_INT_MAX); //(int)9223372036854775807

最大値に+1すると...

<?php 

var_dump(PHP_INT_MAX + 1); //double(9.2233720368548E+18)

double型になります。int値に収まらなくなったため、格納できる型に変換されるのは合点がいきます。

続いて、int値を超えたdouble型で、int値にキャストしようとすると、思わぬ結果が得られます。

<?php 

var_dump(intVal(PHP_INT_MAX + 1)); //int(-9223372036854775808)

マイナス値になりました。見事に真反対な結果が得られました。

ちなみに、PHP_INT_MAX + 1では最小値になりましたが、他の値だと結果が変わるため必ず最小値になるわけではないです。

PHPマニュアルでは、下記の記載があります。


float が整数の範囲 (通常は、32 ビットプラットフォームでは +/- 2.15e+9 = 2^31、Windows 以外の 64 ビットプラットフォームでは +/- 9.22e+18 = 2^63 ) を越える場合、結果は undefined となります。これは、 その float が正しい整数の結果を得るために十分な精度を得られなかったからです。 この場合、警告も通知も発生しません!


整数の範囲を超えた場合の結果は、未定義のため動作は保証しないよって事だと思います。

マイナス値になったり、予想外の挙動を起こすため気をつけましょう。


今回学んだ事

回復力を9223372036854775807より高めすぎると、ヘブン状態になって死にます。


補足


NaN や無限大を integer にキャストした結果は 未定義でプラットフォーム依存でしたが、PHP 7.0.0 以降は常にゼロとなります。


7.0以降は、ゼロになるようです。