我们都知道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}}
这种方法的唯一流程是它依赖于有符号数字的正确位移算术,根据标准,它不一定是这种情况。是否有更快速和/或更便携的解决方案?
答案 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
用作“一种布尔值”来表示数字是否已签名。