如何安全计算两个无符号整数的绝对差并规避溢出?含差值比较场景
无符号整数绝对差无溢出处理方案
问题本质
无符号整数减法不存在传统意义上的“溢出”,只有模2^N的循环回绕(wrap-around):当a < b时,a - b会得到一个极大的无符号数(比如8位无符号数中3-5=254),此时调用abs()完全无效——因为abs()针对有符号整数设计,无符号数传入后会被错误解析,无法得到正确的绝对差。
针对|a - b| < c的最优无溢出判断
不需要计算绝对差再比较,直接将条件转换为无符号加法的范围判断,全程无分支、无回绕风险:
unsigned int a, b, c; if ((a < b + c) && (b < a + c)) { // 满足|a - b| < c的业务逻辑 }
逻辑验证
- 当
a >= b时,|a - b| < c等价于a - b < c,移项后即为a < b + c,无符号加法即使循环回绕也不影响判断:若b + c回绕为小数值,a必然大于该值,条件不成立,符合实际逻辑。 - 当
a < b时,|a - b| < c等价于b - a < c,移项后即为b < a + c,同样利用无符号加法的特性,无需额外处理。
直接计算无符号绝对差的无溢出方法
如果确实需要获取|a - b|的无符号结果,有两种简洁方案:
- 分支判断写法(直观易懂):
unsigned int diff = (a > b) ? (a - b) : (b - a);
- 位运算写法(无分支,性能更优):
#include <stddef.h> // 用于sizeof unsigned int diff = (a - b) ^ ((a - b) >> (sizeof(unsigned int) * 8 - 1));
原理:当a >= b时,a - b的最高位为0,右移后全为0,异或后结果不变;当a < b时,a - b的最高位为1,右移后全为1,异或后等价于对a - b取反加1,即得到b - a。
内容的提问来源于stack exchange,提问作者pas-calc
相关产品推荐
相关产品推荐

