计算与C中数字符号相反的最快方法

时间:2017-05-19 09:48:37

标签: c performance bit-manipulation

我们都知道inline int sgn(int x) { if(x > 0) { return 1; } else if(x < 0) { return -1; } else { return 0; } } 功能。它可以在C中实现,就像这些内容一样:

inline int sgn(int x)
{
    return (x > 0) - (x < 0);
}

或者,更高效的无分支版本:

inline int asgn(int x)
{
    if(x > 0) {
        return -1;
    } else if(x < 0) {
        return 1;
    } else {
        return 0;
    }
}

我想知道的是计算给定数字符号的相反的最快方法,可以这样编写:

inline int asgn(int x)
{
    return (x >> (sizeof(x) * CHAR_BIT - 1)) | !!x;
}

我知道的最快的方法:

{{1}}

这种方法的唯一流程是它依赖于有符号数字的正确位移算术,根据标准,它不一定是这种情况。是否有更快速和/或更便携的解决方案?

3 个答案:

答案 0 :(得分:10)

你不能改变

的顺序
inline int sgn(int x)
{
    return (x > 0) - (x < 0);
}

inline int asgn(int x)
{
    return (x < 0) - (x > 0);
}

顺便说一句,除非您的输入数据是相当随机的,否则无分支代码可能比&#34; branchy&#34;由于分支预测的代码。最好试用这两个版本,看看哪个版本实际上更快。

答案 1 :(得分:1)

转换为unsigned int。如果有点违反直觉,这个定义得很好。然后你可以访问顶部位而没有任何算术问题。

不能保证两个人的补充,但拥有一个补充机器的机会很低,可能不值得担心。

答案 2 :(得分:-1)

摆脱签名号码的转变。实际上,你不能假设会有算术右移,而无符号数的移位总是很明确。这样的东西应该是无分支和便携的:

#include <limits.h>
#include <stdio.h>

int sgn(int x)
{
  unsigned int msb = (unsigned int)x & (1u << (sizeof(int)*CHAR_BIT-1));
  return !!x - 2*!!(int)msb;
}

int asgn(int x)
{
  unsigned int msb = (unsigned int)x & (1u << (sizeof(int)*CHAR_BIT-1));
  return 2*!!(int)msb - !!x;
}

int main(void) 
{
  printf("%d\t%d\n", sgn(-5), asgn(-5));
  printf("%d\t%d\n", sgn( 5), asgn( 5));
  printf("%d\t%d\n", sgn( 0), asgn( 0));
  return 0;
}

输出:

-1 1
1 -1
0 0
在这种情况下,

msb用作“一种布尔值”来表示数字是否已签名。