我有一个数学函数,它取决于
给出的三个变量{n,a和b} 当n为偶数时,{a = n + 1,b = n}
当n为奇数时,{b = n + 1,a = n}
我的函数被称为很多次,各种n。有没有一种有效的方法来实现它?我认为从长远来看,switch
和if
声明可能效率不高..
编辑:这是一个最小的例子:
void func(int n)
{
int a, b;
if(!(n%2))
{
a=n+1;
b=n;
}
else
{
a=n;
b=n+1;
}
//continue ...
}
答案 0 :(得分:5)
只要使用的数字系统是二进制补码(即-1 == ~0),就可以使用:
int odd = n & 1;
a = n + !odd; // Adds one if n is even
b = n + odd; // adds one if n is odd.
此解决方案同时避免% 2
2
,即使& 1
可能会变得略高于if
,也避免使用if。它应该明显快于% 2
解决方案,并且可能比 int odd = !!(n % 2); // using !! to ensure 0 or 1 value.
a = n + !odd;
b = n + odd;
好一点。
如果不知道数字系统是2的补码(并且数字可以是负数),这将避免if:
{{1}}
这与我的第一个代码的逻辑相同,但避免依赖于两个补码。虽然我不知道任何通用处理器不是今天生产的两个补充(甚至已经在过去20年左右生产 - 毫无疑问有人会告诉我,我错了,有些流行的模特仍在制作......)。
与性能一样,确保你知道什么是瓶颈,并且如果它实际上是最终排在前10位的东西,那么只会“弄乱”代码。并测量新代码和旧代码以及确保新代码实际上是一种改进。
答案 1 :(得分:1)
以下代码将告诉a是偶数还是奇数:
if(a%2==0)
{
a = n+1;
b=n;
}
else
{
b = n+1;
a=n;
}
这称为“模数”或“模数”运算符,并返回左输入的剩余部分除以右输入。如果当a除以2时余数为0,那么两个必须均匀地进入它,因此a是偶数。否则,这很奇怪。
答案 2 :(得分:1)
您可以使用以下内容:
int a = n|1;
int b = (n+1)&~1;
gcc -O3输出(n存储在寄存器eax中)
mov edx, eax
add eax, 1
or edx, 1 //a is in edx
and eax, -2 //b is in eax
使用
时int a = n + 1 - (n&1);
int b = n + (n&1);
给出(n存储在edx中)
mov ecx, edx
mov eax, edx
and ecx, 1
or eax, 1
add edx, ecx
和
int a = n + !(n&1);
int b = n + (n&1);
给出
mov eax, edx
and eax, 1
mov ecx, eax
xor ecx, 1
lea eax, [eax+edx*2]
第一个变体(至少使用gcc)比其他变体少一个指令。然而,根据您的编译器,您必须分析您的代码。
答案 3 :(得分:0)
b = n + (n & 1)
a = n + n + 1 - b
答案 4 :(得分:0)
尝试使用以下内容:
a = n + (n + 1) % 2
b = n + n % 2
但我不确定表演是否会有所不同。在判断之前测量性能。
答案 5 :(得分:0)
你可以试试这个,但是你必须分析一下它的性能是好还是差:
int *p[] = {&a, &b};
*p[n % 2] = n + 1;
*p[1 - (n % 2)] = n;
答案 6 :(得分:0)
另外一种方式:
int a, b;
a = b = n;
{
int p = n & 1;
b += p;
a += p ^ 1;
}
这里:
a
,b
。 p
的较小范围。 &
在一个地方。