首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python中使用位技巧的64位popcount

Python中使用位技巧的64位popcount
EN

Stack Overflow用户
提问于 2020-01-28 06:42:43
回答 2查看 408关注 0票数 0

我想在Python中实现64位popcount的小技巧。我尝试复制this code,如下所示:

代码语言:javascript
运行
复制
def popcount_test(y):
    y -= ((y >> 1) & 0x5555555555555555)
    y = (y & 0x3333333333333333) + (y >> 2 & 0x3333333333333333)
    return ((y + (y >> 4)) & 0xf0f0f0f0f0f0f0f) * 0x101010101010101 >> 56

不幸的是,这是不正确的。我们可以通过在int1234上执行popcount来看到这一点。

代码语言:javascript
运行
复制
popcount_test(1234)
261

bin(1234).count('1')
5

在Python中实现的正确的位技巧是什么?

可以使用以下命令执行进一步的测试:

代码语言:javascript
运行
复制
import random
num = random.randint(0, 2**64-1)
print(popcount_test(num), bin(num).count('1'))
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-28 07:43:59

问题是C版本期望乘法结果只产生低位64位,但是Python使用扩展精度整数,所以你得到了整个结果。您可以通过将结果移位后掩码为8位来修复它:

代码语言:javascript
运行
复制
def popcount_test(y):
    y -= ((y >> 1) & 0x5555555555555555)
    y = (y & 0x3333333333333333) + (y >> 2 & 0x3333333333333333)
    return (((y + (y >> 4)) & 0xf0f0f0f0f0f0f0f) * 0x101010101010101 >> 56) & 0xff

这会产生以下结果:

代码语言:javascript
运行
复制
>>> popcount_test(1234)
5
>>> 
票数 2
EN

Stack Overflow用户

发布于 2020-01-28 06:52:57

为了使解决方案显而易见,我在这里添加了它,但功劳归功于@TimPeters和@Heap-Overflow

代码语言:javascript
运行
复制
def popcount_test(y):
    y -= ((y >> 1) & 0x5555555555555555)
    y = (y & 0x3333333333333333) + (y >> 2 & 0x3333333333333333)
    return ((((y + (y >> 4)) & 0xf0f0f0f0f0f0f0f) * 0x101010101010101)  >> 56) & 0xff

这就是Python在Modules/mathmodule.c中的工作方式

代码语言:javascript
运行
复制
static unsigned long
count_set_bits(unsigned long n)
{
    unsigned long count = 0;
    while (n != 0) {
        ++count;
        n &= n - 1; /* clear least significant bit */
    }
    return count;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59939945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档