如何用位运算与布尔逻辑实现整数abs(x)?代码原理及运算符确认问询
详解位运算实现32位整数绝对值的原理
嘿,这个问题问得特别到位!先明确一下:你提到的^确实是异或(XOR)操作,咱们一步步拆解这个实现的逻辑,核心完全依赖32位有符号整数的补码表示和算术右移的特性。
第一步:获取符号掩码 y = x >> 31
在32位有符号整数的规则里,算术右移会把最高位(符号位)填充到所有空出来的位上:
- 如果
x是正数:最高位是0,右移31位后所有位都是0,也就是y = 0 - 如果
x是负数:最高位是1,右移31位后所有位都是1,对应十进制的-1(因为32位补码中全1的二进制数就是-1)
第二步:计算绝对值 (x + y) ^ y
我们分两种情况拆解:
情况1:x是正数(y=0)
代入后就是(x + 0) ^ 0,异或0不会改变任何位的值,结果就是x本身,正好是正数的绝对值。
情况2:x是负数(y=-1)
这时候要结合补码的特性来理解:
- 首先
x + y等价于x - 1(因为y=-1) - 然后和
y(全1的二进制数)异或,相当于对x-1的每一位按位取反(因为01=1,11=0)
而我们知道,32位负数的绝对值等于对其补码取反加1(也就是~x + 1)。那~(x-1)是不是等于~x + 1?举个实际例子验证:
比如x = -5,二进制补码是11111111 11111111 11111111 11111011
x-1 = -6,补码是11111111 11111111 11111111 11111010- 对
x-1按位取反得到00000000 00000000 00000000 00000101,也就是十进制的5,正好是-5的绝对值
换个角度推导:~(x-1) = ~x + 1,完全符合负数求绝对值的补码规则,所以这个运算就能得到负数的绝对值。
总结
这个实现的精妙之处在于用算术右移生成了适配符号的掩码,通过简单的加法和异或操作,避免了分支判断,完全用位运算完成了绝对值计算——不过要注意,它只适用于32位有符号整数,如果是其他位数的整数,需要调整右移的位数(比如64位整数要右移63位)。
内容的提问来源于stack exchange,提问作者beta_me me_beta




