PHPで扱える整数最大値を超えた場合の計算法
- 結論
BCMath関数を使う
http://php.net/manual/ja/ref.bc.php
たまたま12ケタくらいの数値を扱っていて、
剰余算が-1とか-2、割り切れないくせに0を吐き出すことがあった。
<?php // 適当に多い桁の数値を3で割ったときのあまりを求める。 $no = 600000000111; echo $no % 3 ."\n"; // 実行すると -2 $no = 600851475143; echo $no % 3 ."\n"; // 割り切れないのに 0を返す ?>
最初は自分の剰余算の認識がおかしいのかと思ってしまった。
まぁ普通に考えて・・・ケタあふれてそうだなと思い直し、仕様を調べると、
<?php echo PHP_INT_SIZE; ?>
これでPHPで扱える整数の最大値が求まる。
僕の場合は"4"(=4byte)だったんですけど、完璧環境依存っぽい。
(64bitなら6を扱える。まぁPHPの設定かバージョンにも左右されるのかな。)
つまり僕の環境で使える最大整数値は
2147483647 // 10ケタ・・・!
全然たらん。
しかしそれ以上の数値を扱ってもエラーにはならない。
なぜなら、PHPの仕様でINTをこえちゃうと勝手にFloatにキャストされてしまうそうな。
http://d.hatena.ne.jp/hnw/20100415
<?php // PHP_INT_MAXで扱える最大の整数値が求まる var_dump(PHP_INT_MAX); // int(2147483647) var_dump(PHP_INT_MAX+1); // float(2147483648) ?>
つまり下記のようにするとfloatで計算されていたのですね。
<?php // 適当に多い桁の数値を3で割ったときのあまりを求める。 $no = 600000000111; echo $no % 3 ."\n"; // 実行すると -2 var_dump($no); // float(600000000111) 型をみてみるとFloat ?>
まぁそれでも答えが合致しないのはよくわからないンですけど。。
BCMath関数を使えば解決。
<?php $no = 600000000111; echo bcmod($no, 3) ."\n"; // 0 $no = 600851475143; echo bcmod($no, 3) ."\n"; // 2 ?>
ちゃんとした答えをだしてくれました。