今天,我遇到了一个相当奇怪的问题。我需要计算数字的字符串长度,所以我想出了这个解决方案:
// say the number is 1000
(int)(log(1000)/log(10)) + 1
这是基于数学公式的。
log
10x = log
nx/log
n10
(在这里有解释)。
但我发现,在C中:
(int)(log(1000)/log(10)) + 1
不等于NOT
(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
编辑2:我必须向下取整,因为我想知道数字的位数。
log10(999) + 1 = 3.9995654882259823
log10(1000) + 1 = 4.0
如果我只是四舍五入,那么得到的结果(4)是错误的,因为999有3个数字。