連載
» 2006年05月24日 10時00分 公開

JavaTips 〜Javaプログラミング編:変数をdouble型にしたら例外処理が動作しない

[平野正喜,@IT]

 例外を用いて処理を振り分ける以下のようなコードがあります。

画面1 例外を用いて処理を振り分ける変更前のプログラム(整数版) 画面1 例外を用いて処理を振り分ける変更前のプログラム(整数版)

 メソッドgetNumInfoは、文字列を受け取って数値に変換し、100を割った結果を返すものです。整数に変換できない場合や、分母がゼロになる場合はその旨を返します。

 このプログラムを変更し、int型の整数ではなく、double型の実数に変換するようにしたのが以下のプログラムです。「Integer.parseInt」メソッドを「Double.parseDouble」メソッドに代えただけなのですが、例外処理の一部が動作しなくなってしまいました。

画面2 変更後のプログラム(実数版:問題有り) 画面2 変更後のプログラム(実数版:問題有り)

 見ての通り、「分母がゼロになる」が表示されず、代わり「Infinity」となっています。つまり、「分母がゼロになる場合はその旨を返す」ために用意した例外処理が動作しなくなってしまったことがわかります。これはどういうことでしょうか。

原因は整数と実数の扱いの差

 実は、この現象が起こる原因は、一般的なコンピュータにおける整数と実数の扱いが異なることにあります。

 簡単にいえば、整数はジャストで絶対的な値であり、実数はなんらかの誤差を含むかもしれない概算の値ということです。例えば「1×10のマイナス500乗」は、double型の範囲外なのでアンダーフロー(注)を起こすため、実数の0(0.0)として扱われます。そして、もしも、この「1×10のマイナス500乗」で100を割ることができたとしても、答は「1×10の502乗」になりdouble型の範囲外の巨大な値になります。変更後のプログラムの結果に表示されている「Infinity」はこの計算不能な巨大値「正の無限大」を意味しています。

 ということでJavaでは、整数の0で割るという行為は、明らかなルール違反であり、例外を発生させますが、実数の0で割るという行為は理論的には問題がないので、例外を発生させないと考えられます。

 以上から、実数において「分母がゼロになる」場合には、例外が発生しないことを前提にプログラミングすることが必要です。

注:アンダーフローとは表現できる範囲を下回ることで、オーバーフローはその反対で表現できる範囲を上回ること。Javaでは最大の範囲をカバーするdouble型でも、約1.8×10の308乗が最大。最も0に近い値は4.9×10のマイナス324乗。

Profile

RunDog.org

平野正喜


Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。