1

我有一个数学函数,它取决于由下式给出的三个变量 {n, a 和 b}

{a = n+1, b=n} 当 n 为偶数时

{b = n+1, a=n} 当 n 为奇数时

我的函数被多次调用有各种 n. 有没有一种有效的方法来实现这一点?我认为从长远来看, switchandif语句可能不会那么有效..

编辑:这是一个最小的例子:

void func(int n)
{
    int a, b;
    if(!(n%2))
    {
        a=n+1;
        b=n;
    }
    else
    {
        a=n;
        b=n+1;
    }
    //continue ...
}
4

7 回答 7

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. 

该解决方案既避免了,也避免了 if % 2,甚至 for2可以变得多一点。& 1它应该比if解决方案快得多,并且可能比% 2.

如果不知道数字系统是二进制补码(并且数字可以是负数),这将避免 if:

 int odd = !!(n % 2);  // using !! to ensure 0 or 1 value.
 a = n + !odd;
 b = n + odd;

这与我的第一个代码的逻辑相同,但避免依赖二进制补码。虽然我不知道今天生产的不是二进制补码的任何通用处理器(或者甚至在过去 20 年左右一直在生产 - 毫无疑问有人会告诉我我错了,有些流行的模型仍在制造中……)。

与性能一样,请确保您知道什么是瓶颈,并且只有在代码实际上排在前 10 位时才“弄乱”代码。并测量新代码和旧代码以确保新代码实际上是一种改进。

于 2013-06-13T11:54:47.320 回答
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)比其他变体少一条指令。然而,根据您的编译器,您必须分析您的代码。

于 2013-06-13T12:07:14.817 回答
1

以下代码将判断 a 是偶数还是奇数:

if(a%2==0)
{
    a = n+1;
    b=n;
}
else
{
    b = n+1;
    a=n;
}

这称为“模数”或“模数”运算符,并返回左输入除以右输入的余数。如果 a 除以 2 时余数为 0,则 2 必须均匀进入,因此 a 是偶数。否则,就很奇怪了。

于 2013-06-13T11:50:05.017 回答
0

作为另一种方式:

int a, b;
a = b = n;
{
    int p = n & 1;
    b += p;
    a += p ^ 1;
}

这里:

  • 批量复制到a, b
  • 帮助编译器检测较小的p.
  • &在一个地方。
于 2013-06-13T12:04:57.207 回答
0
b = n + (n & 1)
a = n + n + 1 - b
于 2013-06-13T11:54:43.243 回答
0

试试这个,如果没有:

a = n + (n + 1) % 2
b = n + n % 2

但我不确定性能是否会有所不同。在判断之前测量性能。

于 2013-06-13T11:55:08.033 回答
0

You could try this, but you'd have to profile to see whether its performance is better/worse:

int *p[] = {&a, &b};
*p[n % 2] = n + 1;
*p[1 - (n % 2)] = n;
于 2013-06-13T11:55:35.137 回答