1

for ループがあり、変数を毎回 0.1 ずつインクリメントしたいのですが、値がインクリメントとは異なる方法で変化し、その理由がわかりません。

for ループを単純化しましたが、それでも奇妙な出力が得られます。

for (my $t = 1000; $t < 1500 ;$t+=0.1) {
print "$t\n";
}

それは印刷します:

1034.9
1035
1035.1
1035.2
1035.3
1035.4
1035.49999999999
1035.59999999999
1035.69999999999
1035.79999999999
1035.89999999999
1035.99999999999
1036.09999999999
1036.19999999999
1036.29999999999
[it then goes on like this to 1500]

小数点以下の桁数がどこから来ているのかわかりません。これは私の Perl の理解に問題がありますか?

前もって感謝します。

4

4 に答える 4

9

1/10 は、1/3 が 10 進数であるのと同様に、2 進数で周期的な数です。浮動小数点数として正確に表すことはできません。

$ perl -e'printf "%.20g\n", 0.1'
0.10000000000000001

浮動小数点数を許容誤差を伴わずに別の数値と比較しないでください。また、誤差の蓄積に注意してください。

ここで、整数を使用して算術演算を行い、必要に応じて浮動小数点数を生成する簡単なソリューション

for (my $tx10 = 10000; $tx10 < 15000; ++$tx10) {
   my $t = $tx10/10;
   print "$t\n";
}

これは次のように単純化されます

for my $tx10 (10000..14999) {
   my $t = $tx10/10;
   print "$t\n";
}

         ____            ____             ____
0.1 = 0.00011    0.4 = 0.0110    0.7 = 0.10110
        ____                              ____
0.2 = 0.0011     0.5 = 0.1       0.8 = 0.11001
         ____            ____             ____
0.3 = 0.01001    0.6 = 0.1001    0.9 = 0.11100
于 2013-10-29T18:43:45.953 に答える