剑指offer:二进制中1的个数(Python)& 0xffffffff

剑指offer:二进制中1的个数(Python)& 0xffffffff题目描述输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。解题思路思路1首先,这种基础的求二进制中1的个数的问题,对于强大的Python,一定存在一些好用的库函数。果不其然,代码如下:Python代码1defNumberOf1(self,n):ifn>=0:returnbin(n).count(‘1’)else…

大家好,又见面了,我是你们的朋友全栈君。

题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

解题思路
思路1
首先,这种基础的求二进制中1的个数的问题,对于强大的Python,一定存在一些好用的库函数。果不其然,代码如下:

Python代码1

def NumberOf1(self, n):
    if n >= 0:
        return bin(n).count('1')
    else:
        return bin(n & 0xffffffff).count('1')

或者

def NumberOf1(self, n):
    return bin(n & 0xffffffff).count('1')

思路2
思路1虽然简单,但太没意思了。这基本上就直接无视了解题的乐趣,想必也不是出题人的本意。如何在不用Python自带的库函数的情况下灵巧求解呢? 
可以将n上的每一位与1取与,统计1的个数;在求解的过程中每次循环时1左移一位,即n<<1 。但有更漂亮的解法:

如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。
把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。—-牛客网
举例来说,6的二进制是 110 ,6-1=5的二进制是 101,6&5=100, 如此操作之后6中原来的110变为100,循环计数统计1的个数,直至n变为0为止。

Python代码(Wrong)

def NumberOf1(self, n):
    count = 0
    while n != 0:
        count += 1
        n = n & (n-1)
    return count

但是!上述代码在n小于0时会无限循环!(Python3.6.1中) 
打印n 和 n的二进制表示的值,发现了一个很奇怪的现象。以n=-10举例: 
初始时n的二进制值为:

‘0b11111111111111111111111111110110’

循环计数29次后,n的10进制值为:-2147483648,n的二进制值为:

‘0b10000000000000000000000000000000’

循环计数30次后,n的10进制值为:-4294967296,n的二进制值为:

‘0b0’

也就是说,此时虽然n的二进制值为0b0,但是内存中显示n的十进制值为-4294967296,满足 n!=0 的条件, 循环会继续执行。在此之后的循环中,n的二进制表示一直显示为0b0, 但内存中n的十进制数继续不断减少。。。 
为什么呢? 
我在获取上述n的二进制值时,用的语句是:

print(bin(n & 0xffffffff ))
1
而直接调用bin语句,会发现:

bin(-10)
'-0b1010'
bin(-12)
'-0b1100'
bin(-16)
'-0b10000'
... ...
bin(-2147483648)
'-0b10000000000000000000000000000000'
bin(-4294967296)
'-0b100000000000000000000000000000000'
bin(-8589934592)
'-0b1000000000000000000000000000000000'
bin(-17179869184)
'-0b10000000000000000000000000000000000'

即在当前情况下,继续循环时n的二进制不断补0,使得n继续不断减小。。。也就是说Python3.6.1中int类型不止32位。。。

问了度娘之后才知道,原来Python2的int类型有32位和64位一说,但到了Python3,当长度超过32位或64位之后,Python3会自动将其转为长整型,长整型理论上没有长度限制。

Python代码(Rignt)

def NumberOf1(self, n):
    count = 0
    while n&0xffffffff != 0:
        count += 1
        n = n & (n-1)
    return count

另:

class Solution:
    def NumberOf1(self, n):
        if n >= 0:
            print(bin(n), bin(n).count('1'))
            return bin(n).count('1')
        else:
            print(bin(n),bin(n).count('1'))
            print(n,bin(n & 0xffffffff))
            return bin(n & 0xffffffff).count('1')

if __name__ == '__main__':

    sl=Solution()
    print(sl.find(num,k))

    print("正数:")
    print(sl.NumberOf1(3))

    print("负数:")
    print(sl.NumberOf1(-1))
    print("负数:")
    print(sl.NumberOf1(-2))

输出结果如下:

正数:
0b11 2
2
负数:
-0b1 1
-1 0b11111111111111111111111111111111
32
负数:
-0b10 1
-2 0b11111111111111111111111111111110
31

这也是为什么当n是负数的时候,不能使用bin(n).count(‘1’)这个做法,因为n是负数时该式子不成立。

——————— 
作者:goddaniel 
来源:CSDN 
原文:https://blog.csdn.net/u010005281/article/details/79851154
版权声明:本文为博主原创文章,转载请附上博文链接!

 

Python有一个和其他语言完全不一样的地方,就是对负数的二进制表示。Python里的数是无所谓Overflow的,即没有位数限制,因此也就无所谓补码,因为补码都是相对于位数来说的,32位补码和16位补码,肯定是不一样的。但是这样就导致了一个问题,就是无法直接得到32位二进制补码。

在计算机中,负数以原码的补码形式表达。

负数与二进制换转方法:https://blog.csdn.net/shenhaiwen/article/details/79001039

0xffffffff是多少? :https://blog.csdn.net/yew1eb/article/details/8718190?locationNum=1&fps=1

关于0xffffffff 到底是什么意思?:https://blog.csdn.net/wuxinliulei/article/details/9000975

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/145521.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • DNS递归和迭代过程详解

    DNS递归和迭代过程详解目录DNS原理解析DNS进化史DNS结构DNS查询流程DNS服务搭建DNS相关软件的安装服务器搭建规划手把手教你搭建基本DNS服务器搭建主DNS服务器搭建从DNS服务器参考文献DNS原理解析DNS进化史etc/hosts–&gt;NIS–&gt;DNS起初域名和ip地址之间的解析都是完全存放在一个名为hosts的文件当中…

    2022年6月6日
    46
  • Matlab 多个版本的安装包下载、安装教程 + 多套数学建模视频教程

    Matlab 多个版本的安装包下载、安装教程 + 多套数学建模视频教程本文已迁移至:https://www.cnblogs.com/coco56/p/11205999.html如您对电脑操作不太熟悉,需要本人远程帮您安装软件,请查看:https://www.cnblogs.com/coco56/p/13385525.html

    2022年5月30日
    52
  • 通过PropertyDescriptor反映射调用set和get方法

    通过PropertyDescriptor反映射调用set和get方法1packagecom.zhoushun;importjava.lang.reflect.Method;importjava.lang.reflect.Field;importjava.beans.PropertyDescriptor;publicclassPropertyUtil{ @SuppressWarnings(“unchecked”) publicsta

    2022年10月1日
    0
  • 一篇文章教会你使用word域代码(seq field code )

    一篇文章教会你使用word域代码(seq field code )word域代码常常用于自动增长的序列表示,比如论文中的图号、表号。这是一个非常有用的技能,建议花十分钟打开word跟着走一遍。一、域代码的插入、显式、复制、更新Ctl+F9会显式出花括号,中间可以填入域代码,一定是使用Ctl+F9显式出的花括号,不能直接自己打出花括号,如下图所示其中seq表示是序列域代码(sequence),list是自己随便取的域名字。其实这行域代码可以理解成…

    2022年6月12日
    58
  • 阿里巴巴JVM调优工具arthas「建议收藏」

    阿里巴巴JVM调优工具arthas「建议收藏」下载下载全量包从Maven仓库下载最新版本,点击下载:从GithubReleases页下载https://github.com/alibaba/arthas/releases用as.sh启动解压后,在文件夹里有as.sh,直接用./as.sh的方式启动:./as.sh打印帮助信息:./as.sh-h用arthas-boot启动或者在解压后,在文件夹里有arthas-boot.jar,直接用java-jar的方式启动:java-jararth

    2022年5月6日
    68
  • 10条PHP编程习惯助你找工作

    10条PHP编程习惯助你找工作

    2021年10月15日
    35

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号