生成随机的(i,j) 数字对,其中i < 16 和j < 8。如果B[i]&(1<<j) 位置的位未设置,则设置它并增加“count”。循环直到“count”达到“n”。
一点代码(未经测试):
void generate_n_bit_mask ( unsigned char B[], int n )
{
// avoid infinite loop later on.
for ( int i=0; (i < 16); ++i ) {
B[i] = 0;
}
// invariant: k is number of currently masked bits.
for ( int k = 0; (k < n); )
{
// select bit at random.
int i = rand() % 16;
int j = rand() % 8;
unsigned char mask = 1 << j;
// set it if not selected previously.
if ( (B[i]&mask) == 0 ) {
B[i] |= mask, ++k;
}
}
}
练习,迎接挑战:从代码中删除魔法常数16。
编辑:您的 cmets 中建议的修改包含一个令人讨厌的错误。这是一个测试程序,用于处理输出掩码中位的分布方式。
#include <iostream>
#include <iomanip>
#include <ctime>
void generate_n_bit_mask ( unsigned char B[], int n )
{
// avoid infinite loop later on.
for ( int i=0; (i < 16); ++i ) {
B[i] = 0;
}
// invariant: k is number of currently masked bits.
for ( int k = 0; (k < n); )
{
// select bit at random.
int i = std::rand() % 16;
int j = std::rand() % 8;
unsigned char mask = 1 << j;
// set it if not selected previously.
if ( (B[i]&mask) == 0 ) {
B[i] |= mask, ++k;
}
}
int j = 0;
}
// count number of set bits in a byte.
int bit_count ( unsigned char x )
{
int n = 0;
for ( int i = 0; (i < 8); ++i ) {
n += ((x >> i) & 1);
}
return (n);
}
// count number of set bits in 16 bytes.
int total_bit_count ( unsigned char B[] )
{
int n = 0;
for ( int i = 0; (i < 16); ++i ) {
n += bit_count(B[i]);
}
return (n);
}
int main ( int, char ** )
{
std::srand(std::time(0));
unsigned char B[16];
// for all possible values of "n"
for ( int i = 0; (i <= 16*8); ++i )
{
// generate a 16 byte mask with "n" set bits.
generate_n_bit_mask(B, i);
// verify that "n" bits are set.
int n = total_bit_count(B);
if ( n != i ) {
std::cout << i << ": " << n << std::endl;
}
}
}
当这个程序运行时,它将尝试从0 到16*8 的每个n 值,并生成一个带有n 位的随机掩码,然后验证是否设置了n 位。如果发生任何错误(对于n 的某个值,设置了一些k!=n 位),则会输出一条消息。
如果我将条件更改为if ( (B[i]^mask) != 0 ),我会在输出中得到一致的错误。每次运行都会产生至少 1 条错误消息。原始条件 if ( (B[i]&mask) == 0 ) 始终产生 0 条错误消息。