如何计算整数类型的未知bitcount的汉明权重(也就是人口数,即整数中的1位数)?

时间:2016-06-08 19:54:26

标签: c gcc

在C中,如何有效地计算具有可变宽度类型的整数的汉明权重,例如, uint_fast8_t或uintmax_t?

  • 我无法对shift and add算法进行编码,因为直到编译时我才知道该数字中有多少位。
  • 我不能使用__builtin_popcount()系列函数,因为我不知道给定类型的'unsigned int','unsigned long int'或'unsigned long long int'对应于哪个(如果有的话)。
  • 我甚至无法为每个可能的长度编写一个具有单独案例的函数,并且在编译时选择了正确的函数,因为sizeof()在预处理器条件中不可用。

注意:

  • 我正在使用GCC进行编译
  • 如果可能的话,我更喜欢使用__builtin_popcount()函数的解决方案,这样我就可以利用处理器级别的popcount操作。
  • 我没有主动针对任何异常架构,因此假设所有整数类型都是8 * 2 ^ n位长,其中0 <= n <= 4是可接受的解决方案。也就是说,我的其余代码都是非常不可知的非典型字符或整数大小,所以维护该属性会很好。

3 个答案:

答案 0 :(得分:4)

  

如何有效地计算具有可变宽度类型的整数的汉明权重,例如, uint_fast8_t或uintmax_t?

     

[...]

     

我正在使用GCC进行编译

     

我更喜欢使用__builtin_popcount()函数的解决方案

您可以根据相关类型if / else撰写sizeof()声明:

int weight(uintmax_t x) {
    if (sizeof x <= sizeof int) {
        return __builtin_popcount(x);
    else if (sizeof x <= sizeof long) {
        return __builtin_popcountl(x);
    else {
        return __builtin_popcountll(x);
    }
}

GCC很有可能认识到关系表达式是编译时常量,因此优化所有这些只是调用适当的内置函数。

或者,您可以使用__builtin_popcountll(x);据我所知,GCC没有提供比long long int更宽的整数类型,因此在所有情况下都会产生正确答案。

或者您可以确定在特定于机器的构建配置期间选择哪个替代方案(例如,通过Autoconf或CMake测试),并定义一个符号,指示GCC选择哪些可用的变体。此变体还允许您提供回退,以防您意外地遇到宽于long long int的整数类型。

任何这些(除了后备)都可以让你通过一次调用合适的内置来计算汉明重量。我认为,与需要多次通话的替代方案相比,您更有效地表现出对高效性能的明显兴趣。

答案 1 :(得分:3)

假设有问题的类型是 unsigned

获取有问题的数字,抓住低8位,转换为__builtin_popcount(),然后转到int count_bits(some_type x) { int count = 0; while (x > 0) { count += __builtin_popcount((uint8_t)(x & 0xFF)); x >>= 8; } return count; } 。向右移8位并重复直到你得到0。

\r

答案 2 :(得分:-1)

您不需要知道该数字中有多少位。你只需要知道什么时候没有设置。对于简单的无符号类型 - 它将为零。

this.controller.get('email)