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
?>

ちゃんとした答えをだしてくれました。