我尝试仅使用按位运算符来实现符号函数。我知道如果我只想提取有符号整数的符号位,我可以这样做:(x >> 31) & 1
。
另外,我知道条件可以写成布尔表达式:
相当于if(x) a=y else a=z
的 a = x ? y:z
可以改写为:
a=( (x<<31) << 31 ) & y + ( !x << 31) >> 31) & z
,假设x = 1或0。
这个问题有点棘手,因为我有3个条件场景:
如果为正则返回1,如果为零则返回0,如果为负则返回-1。
我认为为了正确执行此操作,我需要使用!
运算符以及!0x<nonzero #>=0
,!0x0=1
,!0x1=0
这一事实。
所以我想出了类似的东西,这是不正确的:
/*
* sign - return 1 if positive, 0 if zero, and -1 if negative
* Examples: sign(130) = 1
* sign(-23) = -1
* Legal ops: ! ~ & ^ | + << >>
*/
int sign(int x) {
return (x>>31) & -1 ) + ( !( !x >> 31 ) & 1;
}
我想我已经完成了所有的工作但不太确定如何将它们放在一起。任何帮助表示赞赏。
谢谢。
答案 0 :(得分:9)
bit hacks page表示这个表达式:
sign = (v != 0) | (v >> 31);
可以在没有!=
的情况下重写它:
sign = (!!v) | (v >> 31);
我更喜欢这种不使用位操作的表达式(来自同一页面)。
sign = (v > 0) - (v < 0);
答案 1 :(得分:0)
如果右移是二进制的,而不是算术的,那么这个也有效:
unsigned int x;
static_assert (sizeof(x) == 4);
(~ (!!x)) + 1 + ( ( (x+0x7FFFFFFF) & 0x80000000 ) >> 30 )
或
(~ (!!x)) + 1 + ( ( !!( (x+0x7FFFFFFF) & 0x80000000 ) ) << 1 )
说明:
(~ (!!x)) + 1
给出0表示x == 0,否则为-1。
( ( (x+0x7FFFFFFF) & 0x80000000 ) >> 30 )
为x> 0提供2,否则为0。