【发布时间】:2009-03-24 23:04:45
【问题描述】:
我有一些代码对 64 位整数进行了大量比较,但是它必须考虑数字的长度,就好像它被格式化为字符串一样。我不能改变调用代码,只能改变函数。
最简单的方法(除了.ToString().Length)是:
(int)Math.Truncate(Math.Log10(x)) + 1;
但是,这表现相当差。由于我的应用程序只发送正值,并且长度相当均匀地分布在 2 和 9 之间(对 9 有一些偏差),我预先计算了这些值并使用了 if 语句:
static int getLen(long x) {
if (x < 1000000) {
if (x < 100) return 2;
if (x < 1000) return 3;
if (x < 10000) return 4;
if (x < 100000) return 5;
return 6;
} else {
if (x < 10000000) return 7;
if (x < 100000000) return 8;
if (x < 1000000000) return 9;
return (int)Math.Truncate(Math.Log10(x)) + 1; // Very uncommon
}
}
这可以通过平均 4 次比较来计算长度。
那么,我还有什么其他技巧可以让这个功能更快吗?
编辑:这将作为 32 位代码 (Silverlight) 运行。
更新:
我采纳了 Norman 的建议,稍微改变了 ifs,结果平均只有 3 次比较。根据肖恩的评论,我删除了 Math.Truncate。总之,这推动了大约 10% 的增长。谢谢!
【问题讨论】:
-
我怀疑这已接近最佳状态。不过,我有兴趣看到任何答案;-p
-
我相信你可以将返回稍微简化为'return 1 + (int) Math.Log10(x)'
-
ToString() 方法有多慢?
-
在我的测试中,ToString().Length() 比 if/return 方式慢大约 35 倍。
-
我不懂 C#,但我猜 Math.log(x) 在进行计算之前会将 x 转换为 double。您是否有可能遇到 log(x) 的浮点舍入问题? (例如,对于 10^n,四舍五入到 ~ 10^n - 1^-15)
标签: c# .net performance integer