遇到一些代码,其中通过将数字转换为字符串然后使用len()来确定位数。
Function numOfDigits_len(n As Long) As Long
numOfDigits_len = Len(Str(n)) - 1
End Function
现在虽然这有效,但我知道与任何不使用字符串的方法相比它会很慢,所以我写了一个使用log()的方法。
Function numOfDigits_log(n As Long) As Long
numOfDigits_log = Int(Log(n) / Log(10)) + 1
End Function
将运行时间减少1/2,这很好,但在特定情况下发生了一些奇怪的事情。
n numOfDigits_log(n)
===== ====================
999 3
1000 3
1001 4
它无法正确处理1000
。我认为这是因为浮点和舍入问题。
Function numOfDigits_loop(ByVal n As Long) As Long
Do Until n = 0
n = n \ 10
numOfDigits_loop = numOfDigits_loop + 1
Loop
End Function
写了这个,当数字大于10 ^ 6时,结果变慢了约10%,并且随着n变大,似乎变得越来越慢。如果我是务实的话,这很好,但我想找到更理想的东西。
现在我的问题是,有没有办法准确使用log()方法。我可以做类似
的事情Function numOfDigits_log(n As Long) As Long
numOfDigits_log = Int(Log(n) / Log(10) + 0.000000001) + 1
End Function
但它似乎非常“hacky”。有没有比log()方法更快或更快的更好的方法? 注意:我意识到在很多情况下这种优化是没有意义的,但现在我遇到过这种情况我想“修复”它
答案 0 :(得分:1)
while循环保证正确性,即它不使用任何浮点计算
int numDigits = 0;
while(num != 0) {
num /= 10;
numDigits++;
}
您还可以使用更大的除数
加快速度int numDigits = 0;
if(num >= 100000 || num <= -100000) {
int prevNum;
while(num != 0) {
prevNum = num;
num /= 100000;
numDigits += 5;
}
num = prevNum;
numDigits -= 5;
}
while(num != 0) {
num /= 10;
numDigits++;
}
答案 1 :(得分:1)
我之前已经回答了这个问题,但我找不到了,所以这里是基础知识:
int i = ... some number >= 0 ...
int n = 1;
if (i >= 100000000){i /= 100000000; n += 8;}
if (i >= 10000){i /= 10000; n += 4;}
if (i >= 100){i /= 100; n += 2;}
if (i >= 10){i /= 10; n += 1;}
那是在C中,但你明白了。
答案 2 :(得分:0)
你会喜欢这个。
我们住在一个基地10号码系统!这意味着您所要做的就是ROUND UP。
一些数字的长度ALWAYS = ceiling (log n)
。例如:7456412(一个7位数字)。记录(7456412)= 6.8 ...向上舍入,你有7. log(9999)= 3.9999。向上,它是4。
特殊情况是你不必舍入,或者当你有10的幂时。例如:log(1000)= 3.如果你能检测到你有10的幂,添加一个日志结果,你赢了!
你可以做这种检测的方式就像
double log10;
int clog10;
int length;
log10 = (Log(n) / Log(10)); // can also use a private static final long hardcoded for Log(10)
clog10 = ceiling(log10);
if (Int(log10) == clog10)
length = clog10 + 1;
else
length = clog10;