用位运算实现加减乘除(1)

用位运算实现+-*/

1.加法
2.减法
3.乘法
4.除法
其实计算机处理加减乘除,都是使用位运算的。在计算机的底层全是位运算帮你实现的。计算机不认识什么加减乘除,计算机底层只认逻辑门,只认识与或左移右移之类的,底层都是01信号。但是手写的位运算还是不如java自带的快,因为java虚拟机里面有一定的汇编语言的。自己写的还需要经过翻译。底层的自带的位运算是很快的,但是你在java里使用位运算实现加减乘除,可能还不如java自带的原始的加减乘除快~。
 
a+b怎么算?  
举例:
要知道,异或运算就是无进位相加。异或运算,也叫无进位相加。
这是a^b,无进位相加得到的结果:
a和b&后的结果,再向左移1位,就是进位信息:
原始的a+b 其实就是等于,a+b(无进位信息) + 进位信息。
比如a+b无进位相加得到0111010 = 58,进位信息为1000 = 8,相加得66。
把a+b无进位相加得到的结果记为a' , 进位信息记为b',继续上述过程:a'+b'无进位相加,+ 进位信息:
因为还有进位信息,继续上述过程:
到这一步进位信息没了,a''''+b''''就是答案了。
计算机里面加法的实现就是这套流程。
 
a-b怎么办?  
a-b = a + b的相反数。
b的相反数怎么表示? b的相反数 = ~b + 1
于是就是这么调用:add(a, add(~b, 1))
 
a*b怎么办呢?
来到小学是怎么学乘法的:
二进制的乘法怎么做呢?
其实也是和十进制的乘法一样,如上图,最后将每行的结果相加,我自己草稿算了一下得出如下:
简化一点,想转化为代码,怎么写:
b的第1位是1,我就知道a进去
b的第2位是1,我在a后面补个0,再进去
b的第3位是1,我在a后面再补个0,再进去
b的第4位是0,不进去
代码解释如下,用下图所示的a和b的计算过程来代入代码:
第1次进入while循环,运行到38行,a <<= 1时,如下:
a左移1,b右移1之后:
第2次循环,b !=0,b & 1 = 0,跳过if,a左移1位,b右移1位:
第3次循环,b != 0, b & 1 = 1, a进去,res累加:
紧接着,a左移1位,b右移1位:
此时b=0,循环结束,返回ans。
 
为什么要写b>>>1,右移,左边最高位一律拿0补。
如果写b >> 1,表示最高位拿符号位补,如果b为负数的话,那就一直补1,代码就跑不完了。
 
 
 

代码实现

package com.cy.class05;

/**
 * 位运算实现+-*\\/
 * 测试连接:https://leetcode.com/problems/divide-two-integers
 */
public class Code03_BitAddMinusMultiDiv {

    public static int add(int a, int b) {
        int sum = a;
        while(b != 0) {
            sum = a ^ b;            //无进位相加信息   ->  sum
            b = (a & b) << 1;       //进位信息  -> b   ->  b'
            a = sum;                //无进位相加信息a  ->  a'
        }
        return sum;
    }

    /**
     * 返回n的相反数
     * 相反数 = 取反 + 1
     * -n = ~n + 1
     */
    public static int negNum(int n) {
        return add(~n, 1);
    }

    public static int minus(int a, int b){
        return add(a, negNum(b));
    }

    /**
     * 乘法
     *
     * 右移:
     * b >> 1,表示右移1,最高位拿符号位来补。
     * b >>>1, 表示右移1,最高位一律拿0来补。
     *
     * 支持负数,道理不好解释,负数的情况下到底发生了什么,跟补码有关,你只要知道同样这套方法既支持正数也支持负数。
     */
    public static int multi(int a, int b) {
        int res = 0;
        while(b != 0) {
            if ((b & 1) != 0) {
                res = add(res, a);
            }
            a <<= 1;
            b >>>= 1;
        }
        return res;
    }

    public static void main(String[] args) {
        int a = 7;
        int b = -3;
        System.out.println(multi(a, b));
    }

}
 
 
 
 
 
 
--
posted on 2025-05-04 16:43  有点懒惰的大青年  阅读(53)  评论(0)    收藏  举报