Mic*_*lGG 17 .net c# performance integer
我有一些代码可以对64位整数进行大量的比较,但是它必须考虑数字的长度,就像它被格式化为字符串一样.我无法更改调用代码,只能更改函数.
最简单的方法(除了.ToString().Length)是:
(int)Math.Truncate(Math.Log10(x)) + 1;
Run Code Online (Sandbox Code Playgroud)
然而,这表现得相当糟糕.由于我的应用程序只发送正值,并且长度相当均匀地分布在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
}
}
Run Code Online (Sandbox Code Playgroud)
这样可以用平均4个比较来计算长度.
那么,我有什么其他技巧可以让这个功能更快吗?
编辑:这将作为32位代码(Silverlight)运行.
更新:
我采纳了Norman的建议并且稍微改变了ifs,导致平均只有3个比较.根据Sean的评论,我删除了Math.Truncate.总之,这促进了大约10%的事情.谢谢!
两个建议:
除非分布非常偏斜,否则这种组合可能不会给你带来太大的影响.
来自Sean Anderson的Bit Twiddling Hacks:
查找整数的整数对数10
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
int r; // result goes here
int t; // temporary
static unsigned int const PowersOf10[] =
{1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
t = (IntegerLogBase2(v) + 1) * 1233 >> 12; // (use a lg2 method from above)
r = t - (v < PowersOf10[t]);
Run Code Online (Sandbox Code Playgroud)
通过首先使用上述技术之一来查找日志库2来计算整数对数库10.通过关系log10(v)= log2(v)/ log2(10),我们需要将其乘以1/log2( 10),大约是1233/4096,或1233,然后右移12.需要添加一个,因为IntegerLogBase2向下舍入.最后,由于值t只是一个可能偏离1的近似值,因此通过减去v <PowersOf10 [t]的结果得到精确值.
此方法比IntegerLogBase2多运行6次.通过修改上面的log base 2 table-lookup方法,可以加速(在具有快速内存访问的机器上),以便条目保存为t计算的内容(即pre-add,-mulitply和-shift).这样做将需要总共仅9次操作来找到日志库10,假设使用了4个表(对于v的每个字节一个表).
至于计算IntegerLogBase2,该页面上有几种替代方案.它是各种高度优化的整数运算的绝佳参考.
您的版本的变体也在那里,除了它假设值(而不是值的日志基数10)是均匀分布的,因此执行指数排序的搜索:
以明显的方式查找整数的整数对数10
unsigned int v; // non-zero 32-bit integer value to compute the log base 10 of
int r; // result goes here
r = (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)
当输入均匀分布在32位值时,此方法很有效,因为76%的输入被第一次比较捕获,21%被第二次比较捕获,2%被第三次比较捕获,依此类推(斩波)每次比较后剩余的下降90%).因此,平均需要不到2.6次操作.