码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 一种计算整数位1个数的新方法



    tags: DSA Python

    前言

    最近看阮一峰老师的每周科技周刊, 发现一个有意思的算法1, 具体的方法文章中都写了, 不过这里还是介绍一下具体的思路以及其Python版的实现.

    算法

    一般来说, 计算位1 的个数可以通过下面的两种方法:

    def calcbit1_v1(n):
        return bin(n).count("1")
    
    
    def calcbit1_v2(n):
        ans = 0
        while n:
            tmp = n & 1  # 取最末位
            ans += tmp
            n >>= 1  # 进位
        return ans
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    文中给出的方法是下面这样的:

    def calcbit1_v3(n):
        total = 0
        tmp = n
        while tmp:
            tmp >>= 1
            total += tmp
        return n - total
    
    
    def calcbit1_v4(n):
        diff = n
        while n:
            n >>= 1
            diff -= n
        return diff
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其中v3是为了解释v4.

    下面来看一下为什么这样可以计算出整数二进制表示中1的个数.

    原理

    这个方法基于下面的一个式子:(从二进制表示形式更容易理解)
    n = n 2 + n 4 + n 8 + ⋯ = ∑ k = 0 + ∞ n 2 k n=\frac n2+\frac n4+\frac n8+\cdots=\sum_{k=0}^{+\infty}\frac n{2^k} n=2n​+4n​+8n​+⋯=k=0∑+∞​2kn​
    其中 n n n是实数.

    当 n n n为正整数的时候, 公式就退化成:
    n 2 + n 4 + n 8 + ⋯ ≈ n \frac n2+\frac n4+\frac n8+\cdots\approx n 2n​+4n​+8n​+⋯≈n
    只能找到一个最接近的项数, 使值最接近 n n n.

    从二进制角度, 我们从最低位开始,

    • 如果最低位是0, 右移之后剩下的数与原来的数相比仅仅是做了除以2的操作, 不会留下1, 所以直接加和即可.
    • 如果是 1 1 1, 那么当进行了右移一位操作后, 剩下的数(非零)二进制表示中就少了一个位1, 这个1在右移的过程中被舍弃了, 这也正是我们要统计的数.

    所以, 保留每次右移运算之后剩下的数之和, 然后与原数n相减, 那么就能得到位1的个数了.

    这里剩下的数其实也可以理解为余数, 因为右移本质上是整除2.

    v3

    因为整数的右移一位就相当于整除2, 每移出一个位,总和就减少1。这意味着计算和与数学和之间的差等于设定位的数量。

    例如, 对于 n = 11 n=11 n=11, 其二进制表示为1011,

    • 第一次右移, tmp=5, total=5,
    • 第二次tmp=2, total=7,
    • 最后一次tmp=1, total=8,
    • 用n减去total, 这就得到了数11的位1个数为3.

    v4

    这个方法更加简便, 省去了一步减的操作, 除此之外在思路上与v3一致.

    ref


    1. www.robalni.org/posts/20220428-counting-set-bits-in-an-interesting-way.txt; ↩︎

  • 相关阅读:
    Python实现DBSCAN膨胀聚类模型(DBSCAN算法)项目实战
    Java毕业设计之评教评分教务管理系统springboot mybatis
    计算机视觉:基于Numpy的图像处理技术(一):灰度变换、直方图均衡化
    html5期末大作业:基于HTML+CSS技术实现——传统手工艺术雕刻网站(3页)
    Mac Pro 突然不能双击打开文件夹
    Ubuntu18.04安装Moveit框架
    GO实现Redis:GO实现内存数据库(3)
    kubernetes-HPA、rancher
    ClickHouse常用函数速查大全
    [数据分析与可视化] 基于matplotlib-scalebar库绘制比例尺
  • 原文地址:https://blog.csdn.net/qq_41437512/article/details/128044528
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号