使用位运算实现32位整数乘3,溢出返回最值的问题求助
看起来你遇到的问题是正数溢出时,直接计算x<<1 +x得到的结果还是正数,导致你没检测到溢出——比如x=0x7FFFFFFF时,计算结果是0x7FFFFFFD,看起来是正数,但实际真实值已经远超32位有符号整数的最大值了。
我来帮你拆解这个问题:
核心思路:先判断溢出,再计算结果
32位有符号整数的范围是[0x80000000, 0x7FFFFFFF]。要实现x*3且仅用指定运算符,不能只靠计算后的结果符号判断溢出(像0x7FFFFFFF这种特殊情况会漏判),必须先明确溢出/下溢的边界:
- 正数溢出:当
x > 0x7FFFFFFF / 3时,x*3会超过最大值。0x7FFFFFFF/3是715827882.333...,对应的十六进制是0x2AAAAAAA——任何大于这个值的正数,乘3都会溢出。 - 负数下溢:当
x < 0x80000000 /3时,x*3会低于最小值。0x80000000/3是-715827882.666...,对应的十六进制是0xD5555555——任何小于等于这个值的负数,乘3都会下溢。
用位运算实现边界判断
我们不能用比较运算符,所以用减法+符号位判断来实现大小比较:
- 对于正数x,判断
x > 0x2AAAAAAA:用x + (~0x2AAAAAAA +1)实现减法(等价于x - 0x2AAAAAAA),如果结果的符号位为0且结果不为0,说明x更大。 - 对于负数x,判断
x <= 0xD5555555:用x + (~0xD5555555 +1)实现减法(等价于x - 0xD5555555),如果结果的符号位为1或者结果为0,说明x更小或相等。
完整代码实现
int mul3(int x) { const int INT_MAX = 0x7FFFFFFF; const int INT_MIN = 0x80000000; const int POS_THRESHOLD = 0x2AAAAAAA; // 正数溢出阈值:x > 此值则溢出 const int NEG_THRESHOLD = 0xD5555555; // 负数下溢阈值:x <= 此值则下溢 int sign = x >> 31; // 正数为0,负数为0xFFFFFFFF(-1) // 判断正数溢出:x > POS_THRESHOLD int temp_pos = x + (~POS_THRESHOLD + 1); // 等价于x - POS_THRESHOLD int positive_overflow = (!(temp_pos >> 31)) & !!temp_pos; // temp_pos>0时为1 // 判断负数下溢:x <= NEG_THRESHOLD int temp_neg = x + (~NEG_THRESHOLD + 1); // 等价于x - NEG_THRESHOLD int negative_overflow = (temp_neg >> 31) | !temp_neg; // temp_neg<=0时为1 // 综合溢出标志:正数溢出 或 负数下溢 int overflow = (positive_overflow & !sign) | (negative_overflow & !!sign); // 计算正常结果 int result = (x << 1) + x; // 选择返回值:溢出则返回对应极值,否则返回计算结果 int ret_val = (overflow & ((sign & INT_MIN) | (!sign & INT_MAX))) | (!overflow & result); return ret_val; }
关键测试验证
- 当x=0x7FFFFFFF时,
positive_overflow会被置为1,触发溢出返回0x7FFFFFFF,符合预期。 - 当x=0xD5555555时,
negative_overflow被置为1,返回0x80000000。 - 正常数值(比如x=5)会返回15,没有问题。
这个方案覆盖了所有边界情况,完全使用了你允许的运算符,没有依赖其他语法。
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

