繰り返しの制御には浮動小数点数を使わない

例えば、以下のような計算をお願いしたいとします。

  0.0 + 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 0.6 + 0.7 + 0.8 + 0.9 + 1.0 = 5.5

これを実現するために以下のようなプログラムを書いて実行します。

  1 public class Test {
  2   public static void main(String[] args) {
  3     float sum = 0.0F;
  4 
  5     for(float i = 0.0F;i <= 1.0F;i+=0.1F) {
  6       System.out.println("i = " +i);
  7       sum += i;
  8     }
  9     System.out.println("sum = " + sum);
 10   }
 11 }

結果は以下の通り。

~/Desktop 5210 $ java Test
i = 0.0
i = 0.1
i = 0.2
i = 0.3
i = 0.4
i = 0.5
i = 0.6
i = 0.70000005
i = 0.8000001
i = 0.9000001
sum = 4.5

正しい結果が得られていません。
これは、浮動小数点数が値を正確に保持することができないためです。
for文のfloat型変数iに誤差が蓄積され、途中から期待値とは異なる値を保持してしまっています。


これを解決するために、以下のようにプログラムを変更します。

  1 public class Test2 {
  2   public static void main(String[] args) {
  3     float sum = 0.0F;
  4     float x;
  5 
  6     for(int i=1;i <= 10;i++){
  7       x = (float)i/10;
  8       System.out.println("x = " +x);
  9       sum += x;
 10     }
 11     System.out.println("sum = " +sum);
 12   }
 13 }

結果は以下の通り。

x = 0.1
x = 0.2
x = 0.3
x = 0.4
x = 0.5
x = 0.6
x = 0.7
x = 0.8
x = 0.9
x = 1.0
sum = 5.5

for文による繰り返しの制御では浮動小数点数ではなく、整数型を使いました。
これにより、誤差が蓄積されるのをふせぎました。
以下のように、毎回xの値を求めるので誤差が蓄積されません。

x = (float)i/10;

まとめ

繰り返しの制御で浮動小数点数を使うとハマる。(実体験あり。)