6位二进制转为bcd 卡诺图_JAVA中的二进制位基本操作(二)

本文介绍了如何通过位操作计算一个整数二进制表示中1的个数,并详细解析了不用乘除法进行两数相除的位移和减法算法,涉及LeetCode原题的解决方案。
摘要由CSDN通过智能技术生成

1、给定一个 int 类型数值 num,求其二进制表示中 1 的个数:

分析:

以 num = 219 为例:

num                           = 1 1 0 1 1 0 1 1

num - 1                     = 1 1 0 1 1 0 1 0

num & (num -1)    = 1 1 0 1 1 0 1 0

则每次 num & (num -1 ) 就可以 将其 二进制最后面的 1 去掉(变为 0 ),同时 用 一个 count 计数 ,循环以上处理,直至 num 变为0 即可,代码如下:

 int countBit(int num) {        int count = 0;        while (num != 0) {            num = num & (num - 1);            count++;        }        return count;    }    public static void main(String[] args) {        BitCount bitCount = new BitCount();        System.out.println(bitCount.countBit(0b11011011)); // 结果为 :6        System.out.println(bitCount.countBit(0xFFFFFFFF)); // 结果为 :32    }

2、两数相除 (LeetCode 原题 https://leetcode-cn.com/problems/divide-two-integers/)

86a7f95674a2eb505888f47c9f54bd38.png

分析:由于不能使用乘法、除法、mod运算符号,就只能用到 加法、减法、位移来解决;示例 dividend =  191、 divisor = 5 转为 二进制计算,如下:

dividend =  0b10111111           ==> 191 

divisor    = 0b101                     ==> 5 

dividend / divisor = 0b100110 ( ==> 38) 余数 为 0b1 ( ==> 1)

56b5c8466ad459fe3ddd08ebdfd65ae5.png

因此,我们可以用 位移 + 减法来做运算,思路如下:

二进制 每向左移动1位,相当于 乘于 2 ,向右移动1位 相当于除以 2 ,过程如下:

  1.  移位:dividend 大于divisor ,可以使用 divisor 左移;divisor = 5  向左移动 5 位(注意:只能是5位,如果再多左移1 位,就超过 dividend 了 ) ,得到新值:a = 0b10100000 ; ;

  2.  减法:dividend = dividend - a = 0b11111 , 大于 divisor,可以继续 位移  ;

  3.  移位 :101 左移2位 a = 0b10100 

  4. 减法: dividend = dividend - a = 0b11111 - 0b10100 = 0b1011 ,大于 0b101,还可以继续位移;

  5. 位移 : 0b101左移1位 a = 0b1010;

  6. 减法 :dividend = dividend - a = 0b1011 - 0b1010= 0b1 ,小于 0b101,则结束位移 ;

  7. 将以上6步 1 位移的次数 累加起来:

    result  = (第1步 的 1 << 5  )+ (第3步的 1<<2 ) + (第5步的  1<<1  ) 

                = 0b100110

  8. 以上只考虑了正整数的情况,负数 可以先转换为 正整数 ,得到的商 再加一个符号即可;

  9. 考虑 int 的取值范围 ,当 dividend 很大 , divisor 很小的时候,容易溢出;

源码如下:

 public int divide(int dividend, int divisor) {        // 0 不能作为除数        if (divisor == 0) {            throw new IllegalArgumentException("参数异常");        }        // 0 除以 任何数 都是 0        if (dividend == 0) {            return 0;        }        // 任何数 除以 1 ,等于任何数        if (divisor == 1) {            return dividend;        }        // 自己除以自己 得 1        if (dividend == divisor) {            return 1;        }        // 除数 -1 时 , 最小 MIN_VALUE 变成 正整数时,会超出 Integer 的表示范围        if (divisor == -1) {            if (dividend == Integer.MIN_VALUE) {                return Integer.MAX_VALUE;            }        }        // 判断 2个数的符号是不相同        int sign = (dividend >> 31) ^ (divisor >> 31);        if (sign == 0) {            // 2个数 符号相同            sign = 1;        } else {            // 2个数 符号不同            sign = -1;        }        // 全部转换为 正整数计算        // 考虑 Integer.MIN_VALUE 变为 正整数时候,会越界,所以 转换为 long 类型计算        long a = (dividend > 0) ? (long) dividend : 0L - (long) dividend;        long b = (divisor > 0) ? (long) divisor : 0L - (long) divisor;        // 计算 a / b        if (a == b) {            return sign;        }        if (a < b) {            return 0;        }        // 最终返回的结果        long res = 0;        // 最大位移(左移动)的位数        int count = 0;        while (a >= b) {            b <<= 1;            count++;        }        if (count == 0) {            return 0;        }        while (count > 0 ) {            count--;            b >>= 1;            if (a >= b) {                res += 1 << count;                a = a - b;            }        }        if (sign == -1) {            res = 0 - res;        }        return res >= Integer.MIN_VALUE && res <= Integer.MAX_VALUE ? (int) res : Integer.MAX_VALUE;    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值