数値の絶対値を得たい場合、Math.absメソッドを使う方法と、自前で「負の数であれば符号を逆転する」方法がありますが、実はJavaでは「そのどちらを用いても」結果が必ず正の数になるとは限りません。
具体的には、int型およびlong型の最小値の絶対値を得ようとした場合で、下図のとおり、Math.absメソッドを用いても、符号を逆転しても、元の値が返ってきますので「絶対値を取ったはずが、負の数が返ってくる」となります。
これは、int型の最大値(2,147,483,647)が、最小値(-2,147,483,648)の絶対値よりも、1小さいことが原因であり、long型、short型、byte型の場合も同様です。
Javaではこのことへの対処として、例外を発生させたり、範囲外を示すビットパターンを返したりせずに、そのままの値を返すことを明文化しているわけです。
なお、実数においてはこの現象は起こらないため、float型や、double型では絶対値が負の数になることはありません(NaNの場合のみ、NaNを返します)。
さて、short型とbyte型の場合、Math.absメソッドには対応するシグニチャがありませんが、暗黙の型変換によりint型として扱われますので、そのままMath.absメソッドに渡すことができます。しかし、戻り値もint型となってしまいますので、元の型で用いるにはキャストする必要があります。
また、short型、byte型の最小値に対して、符号の逆転で絶対値を得ることはできますが、この結果は元の型ではなく強制的にint型にされてしまいます。その結果、例えば「short shortAbsMin = -(Short.MIN_VALUE);」という式は「型の不一致: int から short には変換できません」というコンパイルエラーになってしまうのです。型を変えずにこのコンパイルエラーを避けるにはキャストするしかありません。
この2つのパターンを試してみると下図のようになります。結果を見てのとおり、この場合においても、「最小値の絶対値は解法にかかわらず元の値に等しい負の数」になってしまうのです。
以上から、「整数の絶対値は常に正の数になる」という前提でのプログラミングは避けた方がよいことが分かります。
Copyright © ITmedia, Inc. All Rights Reserved.