给定无符号整数A(32位)和另一个无符号整数B,其中B的二进制形式表示A的10个“最不可靠”位,扩展A的所有1024个潜在值的最快方法是什么?我想用C做这个。
E.g uint B保证总是有10个1和22 0的二进制形式(10个最不可靠的位)。
例如,假设
A = 2323409845
B = 1145324694
他们的二进制表示是:
a=10001010011111000110101110110101
b=01000100010001000100010010010110
B表示A的10个最不可靠的位。因此,B中设置为1的每个位表示A中的不可靠位。
我想计算通过切换A中的任何10位来创建的所有1024个可能值。
答案 0 :(得分:2)
不能保证这是“最快的”,但这就是我要做的。首先,筛出固定位:
uint32_t const reliable_mask = ~B;
uint32_t const reliable_value = A & reliable_mask;
现在我要预处理一个包含不可靠位的1024个可能值的数组:
uint32_t const unreliables[1024] = /* ... */
最后我会把所有这些组合在一起:
for (size_t i = 0; i != 1024; ++i)
{
uint32_t const val = reliable_value | unreliables[i];
}
要获得不可靠的位,您可以循环遍历[0, 1024)
(甚至可能在现有循环内)并将这些位“扩展”到必需的位置。
答案 1 :(得分:1)
这基本上遵循Kerrek使用的技术,但充实了困难的部分:
int* getValues(int value, int unreliable_bits)
{
int unreliables[10];
int *values = malloc(1024 * sizeof(int));
int i = 0;
int mask;
函数定义和一些变量声明。在此,value
是A
而unreliable_bits
是您的B
。
value &= ~unreliable_bits;
屏蔽掉不可靠的位,以确保对包含一些不可靠位和value
的整数进行“或”运算将产生我们想要的结果。
for(mask = 1;i < 10;mask <<= 1)
{
if(mask & unreliable_bits)
unreliables[i++] = mask;
}
在这里,我们将每个不可靠的位放入一个单独的int中供以后使用。
for(i = 0;i < 1024;i++)
{
int some_unreliables = 0;
int j;
for(j = 0;j < 10;j++)
{
if(i & (1 << j))
some_unreliables |= unreliables[j];
}
values[i] = value | some_unreliables;
}
功能的肉。外部循环遍及我们想要的每个输出。然后,我们使用循环变量i
的最低10位来确定是否打开每个不可靠位,使用整数0
到1023
遍历所有可能性的事实最低的10位。
return values;
}
最后,返回我们构建的数组。这是一个简短的主要内容,可用于使用您的问题中给出的A
和B
的值对其进行测试:
int main()
{
int *values = getValues(0x8A7C6BB5, 0x44444496);
int i;
for(i = 0;i < 1024;i++)
printf("%X\n", values[i]);
}
答案 2 :(得分:1)
您可以在b
中迭代1024个不同的位设置,如下所示:
unsigned long b = 1145324694;
unsigned long c;
c = 0;
do {
printf("%#.8lx\n", c & b);
c = (c | ~b) + 1;
} while (c);
要使用这些来修改a
,您只需使用XOR:
unsigned long a = 2323409845;
unsigned long b = 1145324694;
unsigned long c;
c = 0;
do {
printf("%#.8lx\n", a ^ (c & b));
c = (c | ~b) + 1;
} while (c);
此方法的优点是您不需要预先计算任何表,并且您不需要对1024进行硬编码 - 它将完全基于b
中的1位数进行循环。
使用整数向量指令并行化该算法也是一件相对简单的事情。