我想知道是否有办法在不使用函数调用且仅使用运算符(无控制结构)的情况下获得整数的大小。
如果我在这里使用的术语幅度不正确,我的意思是基本上占用了多少位数。例如。 2468的幅度为4。
否则,最有效的方法是什么?
我能想到的最好的是while ( num /= 10 ) mag++;
,但我只是想知道那里是否有某种黑魔法我不知道。
首选C风格语言的解决方案(C,C ++,Java,C#等)
答案 0 :(得分:1)
数学上你想要⌊log 10 (| x |)⌋+ 1.除非x是0。
您给出的运算符和函数之间的区别是相当随意的。总是可以使用⌊log 10 (| x |)⌋+ 1运算符创建一种语言!
仍然为了它的乐趣,我们可以从创建一个整数日志 10 (x)方法开始,这很容易通过简单比较完成:
//assumes 32-bit int in max value. Add cases accordingly
return (x >= 1000000000) ? 9 : (x >= 100000000) ? 8 : (x >= 10000000) ? 7 :
(x >= 1000000) ? 6 : (x >= 100000) ? 5 : (x >= 10000) ? 4 :
(x >= 1000) ? 3 : (x >= 100) ? 2 : (x >= 10) ? 1 : 0;
我们将为我们获得的任何结果添加1,因此我们甚至不需要添加,我们只是更改结果:
return (x >= 1000000000) ? 10 : (x >= 100000000) ? 9 : (x >= 10000000) ? 8 :
(x >= 1000000) ? 7 : (x >= 100000) ? 6 : (x >= 10000) ? 5 :
(x >= 1000) ? 4 : (x >= 100) ? 3 : (x >= 10) ? 2 : 1;
奖金是这也正确处理x == 0的情况。
现在我们只需要吸收它。
x = x > 0 ? x : -x;
return (x >= 1000000000) ? 10 : (x >= 100000000) ? 9 : (x >= 10000000) ? 8 :
(x >= 1000000) ? 7 : (x >= 100000) ? 6 : (x >= 10000) ? 5 :
(x >= 1000) ? 4 : (x >= 100) ? 3 : (x >= 10) ? 2 : 1;
对于单行而言:
return ((x > 0 ? x : -x) >= 1000000000) ? 10 : ((x > 0 ? x : -x) >= 100000000) ? 9 : ((x > 0 ? x : -x) >= 10000000) ? 8 : ((x > 0 ? x : -x) >= 1000000) ? 7 : ((x > 0 ? x : -x) >= 100000) ? 6 : ((x > 0 ? x : -x) >= 10000) ? 5 : ((x > 0 ? x : -x) >= 1000) ? 4 : ((x > 0 ? x : -x) >= 100) ? 3 : ((x > 0 ? x : -x) >= 10) ? 2 : 1;
问题在于您是否考虑?:
控制结构。它是一个运算符,但它确实是分支的(并且比使用控制结构更具实际影响,但仍然是微观的选择)。
至少应该可以在多线程中进行非分支,让我们看看。
非分支abs很容易:
(x ^ (x >> 31)) - (x >> 31); // assuming 32-bit int, adjust shift accordingly
现在以对数为例,我作弊并查看一些我记不起来的尖锐的黑客行为。我只是打算干这个端口(因为我已经做了C#到目前为止,并且可以坚持使用它),我可以在http://graphics.stanford.edu/~seander/bithacks.html阅读,并留下测试并修复我的任何错误作为练习介绍:
我们首先找到log 2 (x);
int[] MultiplyDeBruijnBitPosition = new int[]
{
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
};
int l = x >> 1; // first round down to one less than a power of 2
l |= l >> 2;
l |= l >> 4;
l |= l >> 8;
l |= l >> 16;
l = MultiplyDeBruijnBitPosition[(uint)(l * 0x07C4ACDDU) >> 27];
现在我们可以用它来找到基数为10的对数:
int[] PowersOf10 = new int[]
{1, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
int t = (l + 1) * 1233 >> 12;
return t - (x < PowersOf10[t]);
答案 1 :(得分:0)
对于计算相关值存在恒定时间“位攻击”,例如the highest bit that is set in a number.这是类似的,因为您想要找到非零的最高位。
但是,由于您对base-10值感兴趣,并且这些方法使用二进制算法,我不确定它们是否可以调整。不过,看看它们的工作原理可能会给你一些想法。