今日、私はかなり奇妙な問題に遭遇しました。数値の文字列の長さを計算する必要があったので、この解決策を思いつきました
// say the number is 1000
(int)(log(1000)/log(10)) + 1
これは数式に基づいています
log
10 x = log
n x/log
n10
(ここで説明)
しかし、Cでは、
(int)(log(1000)/log(10)) + 1
等しくない_
(int) log10(1000) + 1
しかし、そうあるべきです。
このコードを使用してJavaで同じことを試しました
(int) (Math.log(1000) / Math.log(10)) + 1
(int) Math.log10(1000) + 1
しかし、それは同じ間違った方法で動作します。
話は続きます。このコードを実行した後
for (int i = 10; i < 10000000; i *= 10) {
System.out.println(((int) (Math.log10(i)) + 1) +
" " + ((int) (Math.log(i) / Math.log(10)) + 1));
}
私は得る
2 2
3 3
4 3 // here second method produces wrong result for 1000
5 5
6 6
7 6 // here again
したがって、バグは 1000 の倍数ごとに発生するようです。
これをCの先生に見せたら、対数除算時の型変換ミスが原因かもしれないと言われましたが、原因がわかりませんでした。
だから私の質問は
- 数学によると、そうあるべきなのに、なぜ は
(int) (Math.log(1000) / Math.log(10)) + 1
と等しくないのですか。(int) Math.log10(1000) + 1
- 1000の倍数だけ間違っているのはなぜですか?
編集:丸め誤差ではありません。
Math.floor(Math.log10(i)) + 1
Math.floor(Math.log(i) / Math.log(10)) + 1
同じ間違った出力を生成する
2 2
3 3
4 3
5 5
6 6
7 6
edit2:桁数を知りたいので切り捨てます。
log10(999) + 1 = 3.9995654882259823
log10(1000) + 1 = 4.0
丸めただけでも同じ結果 (4) が得られますが、999 は 3 桁なので間違っています。