我正在尝试使用按位运算来确定下一个和上一个偶数。
例如,对于下一个函数:
x nextEven(x)
1 2
2 2
3 4
4 4
以及前一个:
x previousEven(x)
1 0
2 2
3 2
4 4
我有nextEven
函数的想法:value = ((value+1)>>1)<<1;
对于previousEven
函数,例如:value = ((value)>>1)<<1
有更好的方法吗?没有比较和查看值是偶数还是奇数。
谢谢。
答案 0 :(得分:4)
执行右移,然后左移以清除LSB效率不高。
我会使用类似的东西:
previous: value &= ~1;
next: value = (value +1) & ~1;
~1
可以(通常会)在编译时预先计算,因此previous
将在运行时以单个位运算结束。 next
可能最终会成为两个操作(增量,and
),但仍然应该非常快。
关于你可以从转变中获得的最好的结果是,编译器会认识到你只是清楚地知道LSB,并将其优化为你期望它产生的东西。
答案 1 :(得分:3)
你可以做这样的事情
以前的偶数
unsigned prevev(unsigned x)
{
return x-(x%2);//bitwise counterpart x-(x&1);
}
接下来的偶数
unsigned nxtev(unsigned x)
{
return (x%2)+x; //bitwise counterpart x+(x&1);
}
答案 2 :(得分:1)
假设您正在使用unsigned int
s,之前的偶数(匹配您的值 - 我们可以争论先前的2甚至2应该是0等)只是x & ~1u
。接下来甚至是x + 1的前一个。
答案 3 :(得分:1)
像Duff的设备那样的技巧,或者用XOR交换两个变量,或者使用按位运算来计算下一个和前一个偶数似乎聪明,但它们很少。
作为开发人员,您可以做的最好的事情是首先优化可读性,并且只有在确定导致真正的问题的特定瓶颈后才能解决性能问题。
获取前一个偶数的最佳代码(根据您的定义,前一个偶数2为2)只是写出如下内容:
if ((num % 2) == 1) num--; // num++ for next.
或(略高级):
num -= num % 2; // += for next.
让疯狂的优化编译器找出最佳的底层代码。
除非您需要每秒数十亿次执行这些操作,否则可读性始终是您最关心的问题。
答案 4 :(得分:1)
以前偶数:
对于之前的偶数,我更喜欢 Jerry Coffin 的answer
// Get previous even number
unsigned prevEven(unsigned no)
{
return (no & ~1);
}
下一个偶数:
我尝试只使用按位运算符,但我仍然使用一个一元减( - )运算符来获得下一个数字。
// Get next even number
unsigned nextEven(unsigned no)
{
return (no & 1) ? (-(~no)) : no ;
}
使用方法nextEven():
0
,否则为1
获得数字=>的LSB; number & 1
-(~number)
答案 5 :(得分:0)
unsigned int previous(unsigned int x)
{
return x & 0xfffffffe;
}
unsigned int next(unsigned int x)
{
return previous(x + 2);
}