// 方法一:当 a 为正数,b 为负数时可能发生溢出 publicstaticintgetMax1(int a, int b){ int c = a - b; int scA = sign(c); int scB = flip(scA); return a * scA + b * scB; }
// 方法二:不会溢出 publicstaticintgetMax2(int a, int b){ int c = a - b; int sa = sign(a); int sb = sign(b); int sc = sign(c); int difSab = sa ^ sb; int sameSab = flip(difSab); int returnA = difSab * sa + sameSab * sc; int returnB = flip(returnA); return a * returnA + b * returnB; }
publicstaticvoidmain(String[] args){ int a = -16; int b = 1; System.out.println(getMax1(a, b)); System.out.println(getMax2(a, b)); a = 2147483647; b = -2147480000; System.out.println(getMax1(a, b)); // wrong answer because of overflow System.out.println(getMax2(a, b));
给定两个有符号 32 位整数 a 和 b,不能使用算术运算符,分别实现 a 和 b 的加、减、乘、除运算。
加法
异或运算 ^ (a ^ b):两个数无进位相加的结果
与运算 & 后再左移一位((a & b) << 1):两个数的进位结果
使用这两个运算即可实现加法:进位相加结果加上进位结果就是二者的和,因此可以一直重复该过程直到进位结果为 0。具体做法是一直计算 a ^ b 和 (a & b) << 1,直到 (a & b) << 1 == 0,说明不再有进位信息了,则两个数的相加结果就是此时的 a ^ b。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicstaticintadd(int a, int b){ int sum = a; // 当 b == 0 时,代表此时的无进位相加结果就是最终结果(因为没进位了) while (b != 0) { // 无进位相加结果 sum = a ^ b; // a + b 的结果等于 (a ^ b) + ((a & b) << 1) // 那么就更新计算目标,使得 a = (a ^ b),b = (a & b) << 1 // 更新 b 为进位结果 b = (a & b) << 1; // 更新 a 为二者无进位相加结果 a = sum; } return sum; }
减法
a - b 可以转换为 a + (-b)。因此取 b 的相反数后即可使用加法运算得到 a - b 的结果。
publicstaticintdiv(int a, int b){ int x = isNeg(a) ? negNum(a) : a; int y = isNeg(b) ? negNum(b) : b; int res = 0; for (int i = 31; i > -1; i = minus(i, 1)) { if ((x >> i) >= y) { res |= (1 << i); x = minus(x, y << i); } } return isNeg(a) ^ isNeg(b) ? negNum(res) : res; }
publicstaticintdivide(int a, int b){ if (b == 0) { thrownew RuntimeException("divisor is 0"); } if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) { return1; } elseif (b == Integer.MIN_VALUE) { return0; } elseif (a == Integer.MIN_VALUE) { int res = div(add(a, 1), b); return add(res, div(minus(a, multi(res, b)), b)); } else { return div(a, b); } }
// 测试 publicstaticvoidmain(String[] args){ int a = (int) (Math.random() * 100000) - 50000; int b = (int) (Math.random() * 100000) - 50000; System.out.println("a = " + a + ", b = " + b); System.out.println(add(a, b)); System.out.println(a + b); System.out.println("========="); System.out.println(minus(a, b)); System.out.println(a - b); System.out.println("========="); System.out.println(multi(a, b)); System.out.println(a * b); System.out.println("========="); System.out.println(divide(a, b)); System.out.println(a / b); System.out.println("=========");
a = Integer.MIN_VALUE; b = 32; System.out.println(divide(a, b)); System.out.println(a / b); }
Pow(a, b)
方法一:递归
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution{ publicdoublemyPow(double x, int n){ long N = n; return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N); }
publicdoublequickMul(double x, long N){ if (N == 0) { return1.0; } double y = quickMul(x, N / 2); return N % 2 == 0 ? y * y : y * y * x; } }