sign function in C using bit operators only

拟墨画扇 提交于 2019-12-10 21:55:34

问题


I'm trying to implement a sign function using only bitwise operators. I know that if I just want to extract the sign bit of a signed integer, I can do: (x >> 31) & 1.

Also, I understand that conditionals can be written as boolean expressions:

if(x) a=y else a=z which is equivalent to a = x ? y:z can be rewritten as:

a=( (x<<31) << 31 ) & y + ( !x << 31) >> 31) & z, assuming x=1 or 0.

This problem gets a little tricky though because I have 3 conditional scenarios:
return 1 if positive, 0 if zero, and -1 if negative.

I was thinking that in order to do this properly, I need to use ! operator and the fact that !0x<nonzero #>=0, !0x0=1, !0x1=0.

So I came up with something like this, which is incorrect:

/*                                                                              
 * 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;
}

I think I have all the pieces but just not quite sure how to put them all together. Any help is appreciated.

Thank you.


回答1:


The bit hacks page suggests this expression:

sign = (v != 0) | (v >> 31);

It can be rewritten without != like this:

sign = (!!v) | (v >> 31);

(demo on ideone).

I prefer this expression that does not use bit manipulation, though (from the same page).

sign = (v > 0) - (v < 0);



回答2:


This one also works if the right shift is a binary one, rather than an arithmetic one:

unsigned int x;
static_assert (sizeof(x) == 4);

(~ (!!x)) + 1 + ( ( (x+0x7FFFFFFF) & 0x80000000 )  >> 30 )

or

(~ (!!x)) + 1 + ( ( !!( (x+0x7FFFFFFF) & 0x80000000 ) ) << 1 )

Explanation:

(~ (!!x)) + 1 gives you 0 for x==0 and -1 otherwise.

( ( (x+0x7FFFFFFF) & 0x80000000 ) >> 30 ) gives you 2 for x>0 and 0 otherwise.



来源:https://stackoverflow.com/questions/24855863/sign-function-in-c-using-bit-operators-only

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!