面试官问不用加法运算符怎么算两个整数的和这道题蛮有意思的下面用Java 17写6种实现你可以留意一下第一种属于脑筋急转弯的做法。下文的代码是在window 11java 17的环境下执行的。减法取反数学上 a b 等价于 a - (-b)。减号不算加法运算符所以publicstaticintadd(inta,intb){returna-(-b);}一行代码搞定需要注意一个边界情况当b是Integer.MIN_VALUE-2147483648时-b会溢出。Java中int的范围是-2147483648到2147483647最小值取反超出最大值结果还是-2147483648。如果追求严谨可以加一层判断publicstaticintadd(inta,intb){if(bInteger.MIN_VALUE){// MIN_VALUE取反溢出拆成两步来加return(a-Integer.MAX_VALUE)-1;}returna-(-b);}这个方法有点像脑筋急转弯但它确实符合题目要求。位运算半加器这是最经典的答案也是面试中最被期待的那种。核心思路来自数字电路里的半加器。两个二进制位相加结果分两部分本位和用异或XOR得到进位用与AND得到。把这个逻辑扩展到32位整数循环处理进位就是一台软件加法器。publicstaticintadd(inta,intb){while(b!0){// 不考虑进位的和intsuma^b;// 进位左移一位对齐到正确的位置intcarry(ab)1;asum;bcarry;}returna;}我们用以3 5为例把执行过程写出来。3的二进制是00115是0101。第一轮异或得01106与运算得0001左移一位得00102。a变成6b变成2。第二轮异或得01004与运算得0010左移一位得01004。a变成4b变成4。第三轮异或得00000与运算得0100左移一位得10008。a变成0b变成8。第四轮异或得10008与运算得00000。b为0循环结束返回8。进位每轮都往高位推一格直到所有位的进位都消化完。int是32位最多循环32次时间复杂度O(1)空间复杂度O(1)。CPU里的ALU做加法本质上就是这套逻辑的硬件实现只不过用逻辑门代替了位运算符。 面试时如果能从位运算聊到CPU加法器面试官对你的判断会从会写代码升级到懂底层。对数指数利用一个数学恒等式log(e^a × e^b) log(e^(ab)) a b加法被转换成了指数和乘法运算publicstaticintadd(inta,intb){return(int)Math.round(Math.log(Math.exp(a)*Math.exp(b)));}这个方法的问题很多浮点精度不可靠。add(1, 2)的中间结果是Math.log(20.0855…)算出来可能是2.9999999999999996需要round来修正。但round本身也不是万无一失的。数字一大Math.exp就溢出。Math.exp(1000)直接返回Infinity后续运算全部失效。负数处理不了。Math.exp(-5)虽然能算但和正数相乘后取对数的精度更差而且当两个数一正一负时指数值差距巨大浮点数的有效位数不够用。这里展示了一种思路生产环境肯定不能这么玩的。BigIntegerimportjava.math.BigInteger;publicstaticintadd(inta,intb){returnBigInteger.valueOf(a).add(BigInteger.valueOf(b)).intValue();}直接调BigInteger的add方法。代码里没有出现号完全合法。有人可能会说这不是耍赖吗加法运算藏在BigInteger.add()里面。这样说没毛病但换个角度看BigInteger能处理任意大小的整数不存在溢出问题。在金融计算、密码学这些对精度要求极高的领域BigInteger是标准做法没人会用位运算手写一个大整数加法。Stream.reduceimportjava.util.stream.IntStream;publicstaticintadd(inta,intb){returnIntStream.of(a,b).reduce(0,Integer::sum);}用Stream把两个数reduce成一个。这个方法更适合展示编程风格正式环境不要这么用。方法对比方法真正避开加法时间复杂度实用性位运算半加器是O(1)面试考察、教学减法取反否减法内部有加法O(1)特定场景可用对数指数否浮点运算内部有加法O(1)数学演示BigInteger否库函数内部有加法O(1)生产环境尤其大数场景Stream.reduce否lambda里有号O(1)函数式风格演示