首页 > 编程语言 >java位运算实现加减乘除

java位运算实现加减乘除

时间:2024-12-19 09:29:00浏览次数:5  
标签:java divisor int 相除 截断 dividend 加减乘除 231 运算

纯用位运算实现加减乘除,涉及一些基础的位运算知识,代码注释里都已经写清楚。

public class BitOperationCalculate {

    public int add(int a, int b) {
        //a+b=(a^b)+(a&b)<<1=a`+b`=(a`^b`)+(a`&b`)<<1  直到b`为0,此时的a就是结果
        //a`=a^b(a异或b) b`=(a&b)<<1(进位信息)
        while (b != 0) {
            int sum = a ^ b;
            b = (a & b) << 1;
            a = sum;
        }
        return a;
    }

    public int sub(int a, int b) {
        //一个数的负数等于该数取反加1
        //a-b=a+(-b)=a+(~b+1)
        return add(a, add(~b, 1));
    }

    public int multi(int a, int b) {
        int res = 0;
        /**
         * a=3      0011
         * b=4    * 0100
         * ----------------------------
         *          0000
         *         0000
         *        0011
         *       0000
         *------------------------------
         *    =  001100  =12
         * 根据上述计算过程 就可以理解下面的逻辑了
         */
        while (b != 0) {
            if ((b & 1) != 0) {
                res = add(res, a);
            }
            //无符号右移
            b >>>= 1;
            a <<= 1;
        }
        return res;
    }

    private boolean isNegative(int n) {
        return n < 0;
    }

    private int div(int a1, int b1) {
        //转为正数
        int a = isNegative(a1) ? add(~a1, 1) : a1;
        int b = isNegative(b1) ? add(~b1, 1) : b1;
        int res = 0;
        /**
         * a/b
         * 假设 a=2^7*b+2^5*b+2^3*b 那么a/b=2^7+2^5+2^3
         * 计算过程就是 a-2^7*b a-2^5*b a-2^3*b 得到结果 2^7+2^5+2^3
         */
        for (int i = 30; i >= 0; i = sub(i, 1)) {
            //因为b左移涉及符号位,可能会导致变成负数,就会错误,所以用a右移是一个性质
            //包含等号,否则少算一个数
            if ((a >> i) >= b) {
                res |= (1 << i);
                a = sub(a, b << i);
                if (a == 0) {
                    //如果已经减为0了,就代表计算结束了,也代表a可以整除b,可以测一下能整除的一定会走到这
                    //不能整除的不会进来,不能整除的直到for循环结束
                    break;
                }
            }
        }
        //判断正负 返回
        return isNegative(a1) != isNegative(b1) ? add(~res, 1) : res;
    }

    public int divide(int a, int b) {
        //我们知道,Integer.MIN_VALUE没有绝对值 所以int最小值要单独考虑
        if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        } else if (b == Integer.MIN_VALUE) {
            return 0;
        } else if (a == Integer.MIN_VALUE) {
            if (b == sub(0, 1)) {
                //b=-1 直接返回int最大值,否则计算有问题
                return Integer.MAX_VALUE;
            }
            if (b == 1) {
                //b=1 直接返回int最小值,省去计算
                return Integer.MIN_VALUE;
            }
            int res = (div(add(a, 1), b));
            int yu = sub(a, multi(res, b));
            return add(res, div(yu, b));
        }
        return div(a, b);
    }

    public static void main(String[] args) {
        BitOperationCalculate bitOperationCalculate = new BitOperationCalculate();
        System.out.println("23+(-45)= " + bitOperationCalculate.add(23, -45));
        System.out.println("34-(-98)= " + bitOperationCalculate.sub(34, -98));
        System.out.println("-12/4= " + bitOperationCalculate.div(-12, 4));
        System.out.println("-3*4= " + bitOperationCalculate.multi(-3, 4));
        System.out.println("8*9= " + bitOperationCalculate.multi(8, 9));
        System.out.println("-8*-7= " + bitOperationCalculate.multi(-8, -7));
        System.out.println("9*0= " + bitOperationCalculate.multi(9, 0));

        System.out.println("Integer.MIN_VALUE / 3= " + bitOperationCalculate.divide(Integer.MIN_VALUE, 3));
        System.out.println(Integer.MIN_VALUE / 3);
        System.out.println("Integer.MAX_VALUE / 3 " + bitOperationCalculate.div(Integer.MAX_VALUE, 3));
        System.out.println(Integer.MAX_VALUE / 3);
        System.out.println("Integer.MIN_VALUE / -1= " + bitOperationCalculate.divide(Integer.MIN_VALUE, -1));
        System.out.println("Integer.MIN_VALUE / 1= " + bitOperationCalculate.divide(Integer.MIN_VALUE, 1));
        System.out.println(Integer.MIN_VALUE);

    }
}

29. 两数相除 - 力扣(LeetCode)29. 两数相除 - 给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。返回被除数 dividend 除以除数 divisor 得到的 商 。注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231,  231 − 1] 。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。 示例 1:输入: dividend = 10, divisor = 3输出: 3解释: 10/3 = 3.33333.. ,向零截断后得到 3 。示例 2:输入: dividend = 7, divisor = -3输出: -2解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。 提示: * -231 <= dividend, divisor <= 231 - 1 * divisor != 0icon-default.png?t=O83Ahttps://leetcode.cn/problems/divide-two-integers/description/

leetcode运行结果

标签:java,divisor,int,相除,截断,dividend,加减乘除,231,运算
From: https://blog.csdn.net/weixin_56812051/article/details/144448831

相关文章

  • Java学习,查找数组重复元素
    Java中查找数组中的重复元素可以通过多种方法实现,包括使用额外的数据结构(如 HashSet)来跟踪已经遇到的元素,或者使用嵌套循环来比较数组中的每一对元素。使用 HashSet查找:publicclassFindDuplicates{  publicstaticvoidmain(String[]args){    int[]......
  • Java学习,删除数组元素
    Java中数组的长度是固定的,这意味着不能,直接从一个数组中删除元素并期望数组自动调整其大小。可以通过几种方式,来实现删除数组元素的效果。创建一个新数组:publicclassRemoveArrayElement{  publicstaticvoidmain(String[]args){    int[]array={1,2......
  • 浅谈Java注解之Component
    一、Component的介绍@Component是Spring框架中的一个注解,用于将一个类标识为Spring容器中的一个组件,通常用于定义一个服务、工具类或者帮助类。这个注解会告诉Spring框架这个类需要被纳入Spring的IoC(控制反转)容器进行管理。二、Component的特点1、自动注册:被@Component注解......
  • 浅谈Java注解之Autowired
    一、Autowired的介绍@Autowired是Spring框架中的一个注解(Annotation),用于实现依赖注入(DependencyInjection,DI)。它告诉Spring容器在创建bean的时候,自动注入相关的依赖。二、Autowired的特点1、自动注入:@Autowired允许Spring容器在运行时自动将bean的依赖项注入到bean中。......
  • 浅谈Java注解之Builder
    一、Builder的介绍@Builder是Lombok库提供的一个注解,用于自动生成建造者模式(BuilderPattern)所需的代码。建造者模式是一种设计模式,用于创建复杂对象,它将对象的构造与表示分离,使得同样的构造过程可以创建不同的表示。通过@Builder注解,可以简化对象的构建过程,避免手动编写大量......
  • Java学习,数组反转
    Java反转数组,既将数组中的元素顺序颠倒,可以通过创建一个新的数组来存储反转后的元素,或者原地(in-place)反转数组,即不使用额外的数组空间。使用新数组创建一个新的数组,并按照原数组的反向顺序将元素复制到新数组中:publicclassReverseArrayExample1{  publicstaticvo......
  • 2024实测验证可用的股票数据接口集合.:python、JavaScript 、JAVA等实例代码演示教你如
    实测可用的股票数据接口,可以直接点击在浏览器中验证:沪深两市股票列表API接口链接(可点击验证):https://api.mairui.club/hslt/list/b997d4403688d5e66a【实时数据接口】沪深两市实时交易数据接口API接口链接(可点击验证):https://api.mairui.club/hsrl/ssjy/000001/b997d4403......
  • java集合框架的详细学习
     集合框架和数组的区别为什么引入集合概念使用数组具有局限性:是一种固定大小的数据结构,其元素类型和数量在创建时就已经确定,并且无法更改,不使用就浪费了。为了解决数组的局限性,引入容器类的概念。容器可以根据需要动态地增加或减少元素。此外,集合框架还提供了丰富的操作方......
  • JAVA领域驱动设计DDD在B端营销系统的实践15
     1背景通过营销活动实现客户/用户拉新、留存和促活是业界普遍采用的方法。为实现商户增长和留存,美团核心本地商业/商业增值技术部也构建了相应的营销系统来支撑商户的线上营销运营。在系统建设过程中,面临着业务体量大、行业跨度大、场景多样、客户结构复杂,需求多变等挑战。......
  • ZZNUOJ_1341:简单密码破解(C/C++/Java)
    题目描述密码是我们生活中非常重要的东东,我们的那么一点不能说的秘密就全靠它了。哇哈哈. 接下来渊子要在密码之上再加一套密码,虽然简单但也安全。 假设渊子原来一个BBS上的密码为zvbo941987,为了方便记忆,他通过一种算法把这个密码变换成YUANzi1987,这个密码是他的名......