C/C++ 方法中最快/最短计算二进制数字总和/又名二进制中的 1 数
Quickest/Shortest in C/C++ method to calculate sum of digits in binary/aka number of 1s in binary
我喜欢寻找最短的编码方法。我发现需要一种方法来计算以二进制表示的数字的位数(或数字中的 1 数)的总和。我使用过位运算符并发现:
r=1;while(a&=a-1)r++;
其中 a 是数字,r 是计数。 a 是给定的整数。有没有办法缩短这个/改进算法?
最短的源代码长度。
您的解决方案假定a
具有无符号类型。
然而,代码不适用于a = 0
。您可以通过以下方式修复它:
r=!!a;while(a&=a-1)r++;
您可以通过这种方式删除一个字符:
for(r=!!a;a&=a-1;r++);
但这里有一个具有相同源长度的替代解决方案:
for(r=0;a;a/=2)r+=a&1;
正如Lundin所提到的,代码打高尔夫球在Stack Overflow上是题外话。 这是一个有趣的游戏,人们绝对可以磨练他的C技能,尝试制作仍然为给定问题完全定义的最小代码,但生成的代码对于试图在更基本水平上编程的普通读者来说价值不大。
关于您问题的主题部分,计算整数位数的最快方法:这个问题已经过深入研究,并且有几种方法可用。哪一个最快取决于许多因素:
- 代码需要多大的可移植性。某些处理器对此具有内置指令,编译器可能会提供一种通过内部函数或内联程序集生成它们的方法。
- 参数的预期值范围。如果范围较小,则简单的查找表可能会产生最佳性能。
- 参数值的分布:如果几乎总是给出一个特定的值,那么只测试它可能是最快的解决方案。 CPU
- 的具体性能:不同的算法使用不同的指令,不同CPU的相对性能可能会有所不同。
只有仔细的基准测试才能告诉您给定的方法是否优于另一种方法,或者您是否正在尝试优化性能无关紧要的代码。可证明的正确性比微优化重要得多。许多专家认为优化总是为时过早。
对于 32 位整数,一个有趣的解决方案是这样的:
uint32_t bitcount_parallel(uint32_t v) {
uint32_t c = v - ((v >> 1) & 0x55555555);
c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
c = ((c >> 4) + c) & 0x0F0F0F0F;
c = ((c >> 8) + c) & 0x00FF00FF;
return ((c >> 16) + c) & 0x0000FFFF;
}
如果乘法很快,这里有一个可能更快的解决方案:
uint32_t bitcount_hybrid(uint32_t v) {
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
此处详细介绍了不同的解决方案:https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
最快的代码是生成一个查找表,并将变量的值作为索引。uint8_t示例:
const uint8_t NUMBER_OF_ONES [256] =
{
0, // 0
1, // 1
1, // 2
2, // 3
1, // 4
2, // 5
...
8, // 255
};
您将将其用作n = NUMBER_OF_ONES[a];
.
第二快的是生成较小的查找表,以节省ROM。例如,对数字 0 到 15 的半字节查找,然后为数据类型中的每个半字节调用该查找。
请注意,"最短的源代码长度"的要求是无稽之谈,这不是专业人士使用的指标。如果这真的是你所追求的,为了好玩或混淆,那么这个问题在SO上是题外话,应该在 https://codegolf.stackexchange.com 上提出。
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 计算二进制文件中的位数
- 计算大二进制矩阵中小二进制矩阵的出现
- 如何生成统一的随机二进制数以成对计算C++中的汉明距离?
- 在 64 位 Linux armv8 计算机上编译 32 位二进制文件时遇到问题
- 在计算负数的二进制补码时如何实现"+1"加法
- C/C++ 方法中最快/最短计算二进制数字总和/又名二进制中的 1 数
- 手动将二进制表达式计算为十六进制
- 编译后如何计算某些二进制功能(或基本块)的校验和
- 以二进制形式计算连续的 1
- 计算每个子树(二进制搜索树)具有特定属性的叶子的数量
- 如何在没有循环的二进制数字表示中只计算1位
- Wxwidgets 在另一台计算机上运行二进制文件时出现问题
- 为什么这个计算二进制搜索树中节点的递归函数总是返回比预期更大的结果
- 分别计算左右孩子的二进制树
- 计算 c# 中二进制文件符号的频率不起作用,但适用于等效的 c++ 代码
- 如何使用opencv函数计算图像的孔数(二进制)
- 如何使用二进制索引树来计算小于索引值的元素数量
- 以从 a 到 b 的数字的二进制表示形式计算 "1" 位数字的算法
- 是否可以在为Solaris SPARC生成二进制文件的英特尔计算机上编写QT C++项目