有效地检查整数的均匀性/奇数

时间:2013-06-13 11:46:56

标签: c++ function conditional

我有一个数学函数,它取决于

给出的三个变量{n,a和b} 当n为偶数时,

{a = n + 1,b = n}

当n为奇数时,

{b = n + 1,a = n}

我的函数被称为很多次,各种n。有没有一种有效的方法来实现它?我认为从长远来看,switchif声明可能效率不高..

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

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

7 个答案:

答案 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;
}

这里:

  • 批量复制到ab
  • 帮助编译器检测p的较小范围。
  • &在一个地方。