Today, I came across quite strange problem. I needed to calculate string length of a number, so I came up with this solution
// say the number is 1000
(int)(log(1000)/log(10)) + 1
This is based on mathematical formula
log
10x = log
nx/log
n10
(explained here)
But I found out, that in C,
(int)(log(1000)/log(10)) + 1
is NOT equal to
(int) log10(1000) + 1
but it should be.
I even tried the same thing in Java with this code
(int) (Math.log(1000) / Math.log(10)) + 1
(int) Math.log10(1000) + 1
but it behave the same wrong way.
The story continues. After executing this code
for (int i = 10; i < 10000000; i *= 10) {
System.out.println(((int) (Math.log10(i)) + 1) +
" " + ((int) (Math.log(i) / Math.log(10)) + 1));
}
I get
2 2
3 3
4 3 // here second method produces wrong result for 1000
5 5
6 6
7 6 // here again
So the bug seems to occur on every multiple of 1000.
I showed this to my C teacher, and he said that it might be caused by some type conversion error during log division, but he didn't know why.
So my questions are
- Why isn't
(int) (Math.log(1000) / Math.log(10)) + 1
equal to(int) Math.log10(1000) + 1
, while it should be, according to the math. - Why is it wrong only for multiples of 1000?
edit: It is not rounding error, because
Math.floor(Math.log10(i)) + 1
Math.floor(Math.log(i) / Math.log(10)) + 1
produce same, wrong output
2 2
3 3
4 3
5 5
6 6
7 6
edit2: I have to round down, because I want to know the number of digits.
log10(999) + 1 = 3.9995654882259823
log10(1000) + 1 = 4.0
If I just round, I get same result (4), which is wrong for 999, because it has 3 digits.