【Java】输入一个long类型的数,输出该数二进制表示中0的数量

题目描述:

题目解析:

首先我们需要了解的是long类型数据的二进制表示是怎样的。

众所周知,long占8个byte,1byte=8bit,故long占64位。在Java中,long是64位有符号的数据类型。范围是-2^{63}~2^{63}-1,亦即-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807。而二进制数在内存中以补码的形式存储的,正数的补码就是该数转化为二进制,负数的补码为符号位是1,其它位是对应正数的二进制的取反加一。故我们可以得到如下示例:

在回顾了基础知识以后,接下来就可以我们开始做题了~~

方法一: 

最简洁的方法是使用Java中封装的现成的统计整数二进制中1的个数的方法:

public static int getNumberOfDigitZero(long value) {
        return 64-Long.bitCount(value);  //Long.bitCount(value):输出value的二进制中所含1的个数。而long的二进制有64位且二进制数中除了1就是0,故64-Long.bitCount(value)即所求。
}

方法二:

因为正数和负数补码的转化方式不同,故针对这种情况,我们要不就是对正数和负数的操作应该分开处理,要不就是找到一个对正数和负数都可以处理的方法。对于第一种思路我们可以对负数做一些操作,将最高位的符号位1变成0,即n & 0x7FFF_FFFF_FFFF_FFFFL,这样就可以把负数转化成正数了。转化前后唯一区别是最高位由1变成0,所以计算时0的数量时要减1。而对正数的处理就是不断除二,再根据除二的余数计算0的数量。 

public static int getNumberOfDigitZero(long value) {
        int count = 64;
        if(value < 0) {
            value = value & 0x7FFF_FFFF_FFFF_FFFFL;
            count --;
        }
        while(value != 0){
            if(value%2 == 1){
                count--;
            }
            value /= 2;
        }
        return count;
}

方法三:

因为对于二进制数,除二操作与把整数右移一位在数学上是等价的,而且和1做与运算也可以达到取余操作所达到的效果。又因在计算机中,乘除法的效率比位运算低很多,所以我们可以用位运算代替乘除法。

public static int getNumberOfDigitZero(long value) {
    int count = 64;
    if (value < 0){
        value = value & 0x7FFF_FFFF_FFFF_FFFFL;
        count --;
    }
    while (value != 0){
        if ((value & 1) == 1){
            count--;
        }
        value >>>= 1;
    }
    return count;
}

注:Java的右移运算符>>,>>>:

>>  :算术右移运算符,也称带符号右移。按二进制形式把所有的数字向右移动对应位数,低位移出,高位的空位补符号位,即正数补0,负数补1。左边第一位为符号位保持不变。

>>>:逻辑右移运算符,也称无符号右移。按二进制形式把所有的数字向右移动对应位数,低位移出,高位的空位补零。即直接整体右移,用0填充左侧的空位。

对于正数来说两者相同,对于负数来说不同。

方法四:

同样使用位运算,将该数使用“>>>”向右位移一位,这样就自动将该数字的二进制表示的最后一位舍弃掉。然后再将舍弃一位的数左移一位,这样恢复的数就是最后一位是0(左移“<<"是将二进制表示左边移出的数补在右边);当它和原先的数字比较时,如果相同,则表示原先舍弃的那位数字是0,不同则为1。这种方法不用考虑正负数问题了,代码更简洁:

public static int getNumberOfDigitZero(long value) {
    int count = 64;
    while (value != 0) {
        if (value != ((value >>> 1) << 1)) {
            count--;
        }
        value = value >>> 1;
    }
    return count;
}

方法五:

由方法四进一步思考,在位运算中,如果把一个整数减去1在与它本身做与运算,那么就会把该整数二进制表示中最右边一个1变成0。因此可得:

public static long getNumberOfDigitZero(long value) {        
    int count = 64;
    while (value != 0){
        value = value & (value-1);
        count--;
    }
    return count;
}

注:这是博主第一次发文章,若有不足请多指教,欢迎大家一起讨论~~

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值