异或运算能模拟无进位加法,因其按位规则(0⊕0=0、1⊕1=0、0⊕1=1、1⊕0=1)与二进制不进位相加完全一致;进位需用a&b检测同为1的位,再左移1位得到实际进位值。

为什么异或运算能模拟无进位加法
因为二进制加法中,相同位相加不产生进位时的结果,恰好等于异或:0+0=0、1+1=0、0+1=1、1+0=1,和 ^ 完全一致。但异或完全忽略进位——比如 1+1 应该是 0 并向高位进 1,而 ^ 只给出 0,进位信息丢失了。
所以单靠 ^ 只完成“本位结果”,进位得另外算、再叠加。
怎么用与运算和左移提取并处理进位
进位只在两个操作数对应位都为 1 时发生,这正是按位与 & 的行为。但与运算结果表示的是“该位产生了进位”,而进位实际要加到更高一位上,所以必须左移 1 位。
例如:a = 3 (0b11), b = 1 (0b01):
-
a ^ b → 0b10(本位和,无进位) -
a & b → 0b01(进位位置),再<code>(a & b) → 0b10(真正要加的进位值)
此时问题转化为:计算 (a ^ b) + ((a & b) —— 仍是加法,但进位已分离。只要进位不为 0,就得继续迭代。
循环实现时什么时候停止
当某次计算的进位为 0,说明没有位需要再进,此时本位和就是最终结果。不能用 a + b == 0 判断,而要看进位变量是否为 0。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
典型写法:
int add(int a, int b) {
while (b != 0) {
int carry = (unsigned int)(a & b)
<p>注意点:</p>
- 对
a & b做unsigned int强转再左移,避免有符号数左移负值触发未定义行为 - 不能直接用
int carry = (a & b) ,尤其在负数参与时可能溢出或行为不可控 - 循环体里必须先算
carry,再更新a,最后赋给b;顺序错会导致逻辑错误
递归写法和边界注意事项
递归本质相同,只是把循环展开:
int add(int a, int b) {
if (b == 0) return a;
int sum = a ^ b;
int carry = (unsigned int)(a & b)
<p>关键差异在于:</p>
- 递归终止条件是
b == 0,不是a == 0或其他 - 仍需对
a & b强转unsigned int,否则负数输入下可能崩溃或返回错误值 - 实际项目中更倾向循环——避免栈溢出风险,尤其当两数绝对值很大、进位传播多轮时
最易被忽略的是符号位参与运算时的类型安全:C++ 中对负数做位移是实现定义的,不加 unsigned 转换,同一段代码在不同编译器或优化级别下可能表现不一。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










