しろあんのさかな

ふーちゃのエンジニアブログ

javaで値がオーバーフローしないためのlong型とint型の足し算掛け算メモ

気をつけていないと忘れがちなので、メモとして残します。javaでコーディング中についつい大きい値のint*intをやってしまうと値が正しくなかったり、マイナスになったりしてしまうことがあります。これは桁あふれ(オーバフロー)がおきた場合に見られる現象です。 int型は32bit,だいたい109くらい(10bitは210(=1024)≈103です)までの数字しか格納することができません。もし、32bitで表現できる数字以上の値を入れると、32bit以上のbitの値は捨て、下位32bitの値のみが値として格納されるようになります。 なぜマイナスになるかというと、32bit中の上位1ビットは正負の符号を表すようになっており、大きすぎる値はこの上位ビットを反転させてしまうからです。0の時は正、1の時は負を表します。

f:id:taiyaki_future:20190503194722j:plain
intの仕組み

桁あふれはエラーメッセージがでないので、間違っていることに気づきにくいです。特に、長めの計算式を一行で描くときは型に注意しないと値が合わないことがあります。

実験

以下今回用意したコードです。 longに代入する数字はlongを表すLを数字の後につけています。この場合はつけなくても問題ないですが、値がだいたい109より大きい場合、Lなしではコンパイルエラーになります。

f:id:taiyaki_future:20190503185938p:plain
試したコード

以下が実行結果です。 int同士の掛け算、足し算は桁あふれを起こしているのでマイナスになっています。

f:id:taiyaki_future:20190503190215p:plain
実行結果

さらに踏み込んだ実験

さらに踏み込んだ実験として、intとlongの計算順序を変えてやってみました。

f:id:taiyaki_future:20190503195640p:plain
さらに踏み込んだ実験のコード

int型をlongでキャストしたものが正解の値なので、4001000000が正解です。int+int+longでは、値がオーバーフローしてしまっています。int+intまではintとして扱っていると思います。同様の理由で全体をlongでキャストしたものも同じ値になっています。long+int+intだと最初からlong型になってるから正しい値がでているんでしょうね。

f:id:taiyaki_future:20190503195709p:plain
さらに踏み込んだ実験の結果

考えてることメモ

int+int+longでlongが来たときに値を確保するメモリの大きさを変えて入れ直しているのかな。Stringでオブジェクトを作り直すみたいにと思ったので書いておきます。