在许多变量中,是否有任何有效的方法可以在同一位置执行COUNT个? count函数应该用相应位数的1之和填充数组。例如,我们有以下三个变量(我使用8位变量使其变得简单):
uint8_t a = 0xF; // 0000 1111
uint8_t b = 0x3C; // 0011 1100
uint8_t c = 0xF0; // 1111 0000
int result[8];
// some operations ...
count << result[0] << result[1] << .... // prints 1122 2211
我找到了许多解决方案,用于对整个单变量中的那些进行求和,但不是针对上述问题。
答案 0 :(得分:2)
这个小代码完全符合您的要求。您可以通过一个小查找数组轻松扩展它以支持N个变量。注意使用double not操作。将输出拖动为0或1。
#include <iostream>
using namespace std;
int main() {
uint8_t a = 0xF; // 0000 1111
uint8_t b = 0x3C; // 0011 1100
uint8_t c = 0xF0; // 1111 0000
unsigned result[8];
for(int i = 0; i < 8; ++i) {
unsigned mask = 1 << i;
result[i] = !!(a & mask) + !!(b & mask) + !!(c & mask);
}
for(int i = 0; i < 8; ++i)
cout << result[i];
}
答案 1 :(得分:2)
将每个uint8_t
二进制数字扩展为uint32_t
十六进制数字,并且#34;将它们加起来&#34;。好,只要每位不超过15个。
#include <stdio.h>
#include <stdint.h>
// See below for tighter code
uint32_t shift_nibble(uint8_t x) {
uint32_t y = 0;
uint32_t mask = 1;
while (x) {
if (x & 1) {
y |= mask;
}
mask <<= 4;
x >>= 1;
}
return y;
}
void PrintVerticalBitwiseCount(const uint8_t *x, size_t size) {
uint32_t y = 0;
for (size_t i=0; i<size; i++) {
y += shift_nibble(x[i]);
}
printf("%08lX\n", (unsigned long) y);
}
int main(void) {
const uint8_t a[] = { 0xF, 0x3C, 0xF0 };
PrintVerticalBitwiseCount(a, sizeof a/sizeof *a);
return 0;
}
输出
11222211
候选人shift_nibble()
更快。戴上你的八角帽
uint32_t shift_nibble(uint8_t x) {
uint32_t y;
y = UINT32_C(0x01010101) & (UINT32_C(0001010101) * (x & 0x55));
y |= UINT32_C(0x10101010) & (UINT32_C(0010101010) * (x & 0xAA));
return y;
}
答案 2 :(得分:1)
作为模板,我建议在C ++ 11中使用以下函数。返回的列表在每个位的适当位置具有位计数,也就是说,最低有效位计数在位置0,下一位在位置1处等。 希望这有助于某人。
template<typename T>
std::list<long>
vertical_bit_sum(std::vector<T> items)
{
size_t bits = sizeof(T) * 8;
std::list<long> result;
do
{
long count = 0;
for ( T item : items)
{
count += (0x1 & (item >> (bits-1)));
}
result.push_front (count);
--bits;
}
while( bits > 0);
return result;
}
std::list<long> result= vertical_bit_sum<uint8_t>( { 0xF, 0x3C, 0xF0 });
答案 3 :(得分:0)
做这样的事情:
uint64_t accum = 0;
uint64_t table[0x100] = {.. precomputed vals ...};
int count = 0xFF;
while(bytes_available()) {
if(--count == 0) {
count = 0xFF;
for(int i = 0; i < 8; i++)
result[i] = ((uint8_t*)&accum)[i];
accum = 0;
}
accum += table[(uint8_t)get_next_byte()];
}
答案 4 :(得分:0)
对于绝对速度,您可以通过将8个字节打包在一个64位累加器中来并行处理8个计数。
使用256个64位条目初始化查找表,这些条目是扩展为字节的原始8位。 (例如,条目Lookup[0x17u]
映射到0x0000000100010101ul
。)
只需使用
执行计数Acc+= Lookup[Byte];
通过在64位上映射8字节的数组来检索各个计数器。
在溢出发生之前,您可以执行256次累积;如果需要更多,则以256个块累加,并在处理一个块后,将计数传输到更大的累加器。
如果你需要积累不超过16次,32位累加器就足够了。
答案 5 :(得分:-1)
确定变量中某个特定位置的1是否比正常人口计数简单得多。
bool hasOneAtPosition(int position, int target) {
int mask = 1 << position;
return (target & mask) != 0;
}
...只需在所有输入上调用它,并在每次返回true时递增计数器。 Simplez。