首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计数十进制数的二进制格式的1的个数

计数十进制数的二进制格式的1的个数
EN

Stack Overflow用户
提问于 2013-02-04 16:07:16
回答 5查看 22.7K关注 0票数 6

我正在尝试找出一个大的十进制数的二进制形式的1的个数(十进制数可以大到1000000)。

我尝试了这段代码:

代码语言:javascript
复制
while(sum>0)  
{  
    if(sum%2 != 0)  
    {  
        c++;   // counting number of ones  
    }  
    sum=sum/2;  
}  

我想要一个更快的算法,因为它需要很长的时间为大的小数输入。请给我一个有效的算法。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-02-04 16:16:30

在C++中,你可以做到这一点。

代码语言:javascript
复制
#include <bitset>
#include <iostream>
#include <climits>

size_t popcount(size_t n) {
    std::bitset<sizeof(size_t) * CHAR_BIT> b(n);
    return b.count();
}

int main() {
    std::cout << popcount(1000000);
}
票数 19
EN

Stack Overflow用户

发布于 2013-02-04 16:10:41

您正在寻找的是"popcount",它在后来的x64 CPU上实现为单条CPU指令,在速度上不会被击败:

代码语言:javascript
复制
#ifdef __APPLE__
#define NAME(name) _##name
#else
#define NAME(name) name
#endif

/*
 * Count the number of bits set in the bitboard.
 *
 * %rdi: bb
 */
.globl NAME(cpuPopcount);
NAME(cpuPopcount):
    popcnt %rdi, %rax
    ret

当然,您需要首先测试CPU对它的支持:

代码语言:javascript
复制
/*
 * Test if the CPU has the popcnt instruction.
 */
.globl NAME(cpuHasPopcount);
NAME(cpuHasPopcount):
    pushq %rbx

    movl $1, %eax
    cpuid                   // ecx=feature info 1, edx=feature info 2

    xorl %eax, %eax

    testl $1 << 23, %ecx
    jz 1f
    movl $1, %eax

1:
    popq %rbx
    ret

下面是一个用C实现的代码:

代码语言:javascript
复制
unsigned cppPopcount(unsigned bb)
{
#define C55 0x5555555555555555ULL
#define C33 0x3333333333333333ULL
#define C0F 0x0f0f0f0f0f0f0f0fULL
#define C01 0x0101010101010101ULL

    bb -= (bb >> 1) & C55;              // put count of each 2 bits into those 2 bits
    bb = (bb & C33) + ((bb >> 2) & C33);// put count of each 4 bits into those 4 bits
    bb = (bb + (bb >> 4)) & C0F;        // put count of each 8 bits into those 8 bits
    return (bb * C01) >> 56;            // returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
}

GNU C编译器运行时包含一个“内置”,它可能比上面的实现更快(它可能使用CPU popcnt指令,但这是特定于实现的):

代码语言:javascript
复制
unsigned builtinPopcount(unsigned bb)
{
    return __builtin_popcountll(bb);
}

上面的所有实现都用在了我的C++国际象棋库中,因为当使用位板来表示棋子位置时,popcount在国际象棋移动生成中起着至关重要的作用。我使用在库初始化期间设置的函数指针来指向用户请求的实现,然后通过该指针使用popcount函数。

谷歌将提供许多其他实现,因为这是一个有趣的问题,例如:http://wiki.cs.pdx.edu/forge/popcount.html

票数 20
EN

Stack Overflow用户

发布于 2013-02-04 16:10:15

有很多种方法。Brian Kernighan's way很容易理解,而且速度很快:

代码语言:javascript
复制
unsigned int v = value(); // count the number of bits set in v
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v; c++)
{
  v &= v - 1; // clear the least significant bit set
}
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14682641

复制
相关文章

相似问题

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