1. 位运算实现四则运算

2. 加法

异或运算 是一个无进位加法

  1. int a = 46; //0101110
  2. int b = 20; //0010100
  3. System.out.println(a^b); //58 ==> 0111010
  4. System.out.println(a&b); //4 ==> 0000100 进位位置
  5. System.out.println((a&b) << 1);//8 ==>0001000 需要左移一位才是进位后的结果
  6. //不断的无进位加法 + 进位信息 直到进行信息为空则为 加法

完整写法

  1. public static int add(int a,int b) {
  2. int sum = a;
  3. while (b != 0) { //直接进位信息为空
  4. sum = a ^ b; //无进位相加
  5. b = (a&b)<<1; // 进位信息
  6. a = sum; //a变成无进位信息 加法的结果
  7. }
  8. return sum;
  9. }

3. 减法

a - b = a + (-b) = a + (~b + 1)

  1. //减法
  2. public static int sub(int a,int b) {
  3. b = add(~b,1);
  4. return add(a,b);
  5. }

4. 乘法

10. 位运算实现四则运算 - 图1

如果乘数当前位为1,则取被乘数左移一位的结果加到最终结果中;如果当前位为0,则取0加到乘积中

  1. //乘法
  2. public static int multiply(int a, int b) {
  3. int sum = 0;
  4. while (b != 0) {
  5. if ((b & 1) != 0) { //如果b 与 1 不等于0则需要相加
  6. sum = add(sum, a);
  7. }
  8. a = a << 1; //a左移一位0补全
  9. b = b >>> 1; //b右移一位
  10. }
  11. return sum;
  12. }

5. 除法

  1. public static int div(int a, int b) {
  2. int x = a < 0 ? add(~a, 1) : a; // 判断是否为负数 如是则转为绝对值计算
  3. int y = b < 0 ? add(~b, 1) : b;
  4. int res = 0;
  5. for (int i = 30; i >= 0; i = add(i, -1)) { // i-- ==> add(i,-1)
  6. if ((x >> i) >= y) { // 如果x右移i位 >= 被除数 则进入分支
  7. res |= (1 << i); // 将倍数(位数)结果增加到ans中
  8. x = add(x, add(~y, 1) << i); // 减掉n倍的被除数
  9. }
  10. }
  11. return (a < 0 == b < 0) ? res : add(~res, 1); // 判断ab两数符号是否相等 不相等则返回相反数
  12. }

6. 29. 两数相除

  1. // 加法
  2. public static int add(int a, int b) {
  3. int sum = a;
  4. while (b != 0) { // 直接进位信息为空
  5. sum = a ^ b; // 无进位相加
  6. b = (a & b) << 1; // 进位信息
  7. a = sum; // a变成无进位信息 加法的结果
  8. }
  9. return sum;
  10. }
  11. // 减法
  12. public static int sub(int a, int b) {
  13. b = add(~b, 1); // 取反+1
  14. return add(a, b);
  15. }
  16. // 乘法
  17. public static int multiply(int a, int b) {
  18. int sum = 0;
  19. while (b != 0) {
  20. if ((b & 1) != 0) {
  21. sum = add(sum, a);
  22. }
  23. a = a << 1;
  24. b = b >>> 1;
  25. }
  26. return sum;
  27. }
  28. // 除法
  29. public static int div(int a, int b) {
  30. int x = a < 0 ? add(~a, 1) : a; // 判断是否为负数 如是则转为绝对值计算
  31. int y = b < 0 ? add(~b, 1) : b;
  32. int res = 0;
  33. for (int i = 30; i >= 0; i = add(i, -1)) { // i-- ==> add(i,-1)
  34. if ((x >> i) >= y) { // 如果x右移i位 >= 被除数 则进入分支
  35. res |= (1 << i); // 将倍数(位数)结果增加到ans中
  36. x = add(x, add(~y, 1) << i); // 减掉n倍的被除数
  37. }
  38. }
  39. return (a < 0 == b < 0) ? res : add(~res, 1); // 判断ab两数符号是否相等 不相等则返回相反数
  40. }
  41. public static int divide(int a, int b) {
  42. if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) { // a和b都为最小值 返回1
  43. return 1;
  44. } else if (b == Integer.MIN_VALUE) { // 被除数为最小值 返回0
  45. return 0;
  46. } else if (a == Integer.MIN_VALUE) { // 除数为最小值
  47. if (b == add(~1, 1)) { // 被除数为-1 返回最大值
  48. return Integer.MAX_VALUE;
  49. } else {
  50. int c = div(add(a, 1), b); // (a+1)/b = c
  51. int e = multiply(b, c); // b*c = e
  52. int f = add(a, add(~e, 1)); // a-(b*c) = f
  53. int q = div(f, b); // f/b = q
  54. return add(c, q); // c+q
  55. }
  56. } else {
  57. return div(a, b);
  58. }
  59. }