【问题标题】:number of 1's in 32 bit number32 位数字中 1 的个数
【发布时间】:2009-09-22 05:48:20
【问题描述】:

我正在寻找一种在 32 位数字中包含多个 1 的方法 之间不使用循环。 任何人都可以帮助我并为我提供代码或算法 这样做。 提前致谢。

【问题讨论】:

  • 例如你想从 2344 到 2,3,4,4 喜欢吗?请澄清您的输入和所需的输出

标签: java algorithm bit-manipulation


【解决方案1】:

Integer.bitCount(int). 想看怎么用可以参考源码; Integer 类的许多位旋转例程取自 Hacker's Delight.

【讨论】:

  • 是的!既然已经有了可用的方法,为什么还要使用异国情调的破解方法。
  • 使用内建函数也会让未来版本的 JVM 更容易发现 SSE4.2 POPCNT 指令可用于此目的。
  • 我正要发布一个类似于 Michael Foukarakis 的答案,因为在 Integer.bitCount() 实施之前我就是这样做的。感谢您提请我注意新方法。
【解决方案2】:

参见规范参考:Bit Twiddling Hacks

【讨论】:

  • 请记住,Java 整数是始终签名的,并进行相应的修改。
【解决方案3】:

简短、优化的答案(用 C 语言):

int pop(unsigned x) {
   x = x - ((x >> 1) & 0x55555555);
   x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
   x = (x + (x >> 4)) & 0x0F0F0F0F;
   x = x + (x >> 8);
   x = x + (x >> 16);
   return x & 0x0000003F;
}

要了解这种魔法为何起作用,请参阅 The Quest for an Accelerated Population CountBeautiful Code 中的 Henry S. Warren, Jr. 第 10 章。

【讨论】:

  • 但是问题是关于 Java 的,在 Java 中没有无符号的 32 位 int 类型,这不适用于 Java 的有符号 32 位 int。
  • 据我所知,问题中没有提到 Java。也许我错了,但标签不应该用于将问题限制为给定语言。
  • IMO 你错了。如果一个问题被标记为 Java,除了这个问题是关于 Java 的,这还意味着什么?也许提问者还应该在文本中提到他们正在谈论 Java,但如果他们不这样做,我认为我们不应该假装它没有被标记为 Java。如果您可以假设 C 答案是可以接受的,那么我可以假设仅 GCC 的 C 答案是可以接受的,并说使用 __builtin_popcount。但这对提问者没有多大帮助;-)
  • 对于 java,有一个无符号右位移 (>>>)。我认为这会给你正确的结果。虽然可能不是您期望的结果。
  • 用无符号移位(">>>")替换有符号移位(">>"),这段代码正是Java的Integer.bitCount(int)方法中使用的代码。
【解决方案4】:

将 32 位数字拆分为四个 8 位数字(参见位移运算符、强制转换等)

然后使用包含 256 个条目的查找,将 8 位数转换为位数集。添加四个结果,快!

另外,看看 Mitch Wheat 是怎么说的 - 摆弄一下会很有趣 ;)

【讨论】:

    【解决方案5】:

    可以递归定义:

    int bitcount(int x) {
      return (x==0) ? 0 : (x & 1 + bitcount(x/2));
    }
    

    上面的代码未经测试,可能只适用于 x>=0。无论如何,希望你能明白这个想法......

    【讨论】:

    • -1 用于在请求“无循环”时使用递归。当然,它没有使用循环结构,但它仍然在非 O(1) 时间内运行。
    • 对不起。这个问题对我来说就像一个家庭作业问题,我想提供不同的观点。对于任何关键性能以及大多数非理论应用程序,请选择比特旋转解决方案!
    • 经典的是:return (x==0) ? 0 : (1 + bitcount(x & (x - 1)));
    【解决方案6】:

    我个人最喜欢的,直接来自Bit Twiddling Hacks

    v = v - ((v >> 1) & 0x55555555);
    v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
    c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
    

    【讨论】:

    • 注意:这不适用于 Java 的有符号 int 类型——但基本思想是库使用的那个。
    • 我想你想要 >>> 而不是 >>.
    • @finnw:我想你的意思是在 Java 中(因为在 C 中不存在这样的运算符,我第一次看到/使用了这个技巧),在这种情况下你是对的,维护符号是错误的。
    • @Michael,是的,我假设是 Java(问题被标记为 java)
    【解决方案7】:

    以下是 Integer.bitCount 的 JDK 1.5 实现

    public static int bitCount(int i) {
        // HD, Figure 5-2
    i = i - ((i >>> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
    i = (i + (i >>> 4)) & 0x0f0f0f0f;
    i = i + (i >>> 8);
    i = i + (i >>> 16);
    return i & 0x3f;
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 2019-05-17
      • 2011-02-25
      • 2020-10-17
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多