【问题标题】:How to generate n random 1s in an unsigned char array in c/c++?如何在 C/C++ 中的无符号字符数组中生成 n 个随机 1?
【发布时间】:2011-10-13 04:34:11
【问题描述】:

这与我刚才提出的问题不同,而且更具挑战性。

我有一个无符号字符数组,比如说 无符号字符 A[16]。 我需要生成一个掩码向量,将其应用于我的数组 A[16]。

它应该包含n个'1',其中0

我还需要在向量中随机分布的这 n 个 '1'。

如何在 c/c++ 中做到这一点?

谢谢!

编辑: 我的想法如下: 我将生成 n 个随机数(需要进行检查以确保所有 n 个数都不相同)并将它们存储在数组 tmp[n] 中。然后根据shifting生成mask。

srand(time(0));
for(i = 0; i < n; i++){
  for(j = 0; j < i; j++) 
    while(tmp[i] == tmp[j])  // to make sure all n random numbers are different
      tmp[i] = rand()%128;

unsigned char mask[16] 
for(i = 0; i < n; i++) 
  mask[16] |= (1 << tmp[i]);  //generate mask

【问题讨论】:

  • 你很好地陈述了你的要求,但你没有具体说明你做了什么以及你对解决这个问题有什么想法。这看起来像家庭作业,除非你发布你的努力,否则这将关闭很快。
  • 这不是家庭作业...但我可以发布我的努力

标签: c++ c random


【解决方案1】:

生成随机的(i,j) 数字对,其中i &lt; 16j &lt; 8。如果B[i]&amp;(1&lt;&lt;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;
        }
    }
}

当这个程序运行时,它将尝试从016*8 的每个n 值,并生成一个带有n 位的随机掩码,然后验证是否设置了n 位。如果发生任何错误(对于n 的某个值,设置了一些k!=n 位),则会输出一条消息。

如果我将条件更改为if ( (B[i]^mask) != 0 ),我会在输出中得到一致的错误。每次运行都会产生至少 1 条错误消息。原始条件 if ( (B[i]&amp;mask) == 0 ) 始终产生 0 条错误消息。

【讨论】:

  • 你真的需要逗号操作符吗?
  • 应该是j 而不是(j-1)
  • @K-ballo:是的。它强调这两条指令实际上是算法中的一个逻辑步骤。
  • @ChristianRau:感谢您发现这一点。
  • 这不是我想要的。因为如果 n = 2,我可以在 B[0] 中有两个 1。如果您更改为if ( B[i]^mask != 0)。然后就可以了。
【解决方案2】:

你有一个由 16 个unsigned chars 组成的数组,可以看作是 16 * 8 位。要生成其中包含n 1 位的随机掩码,请在 [0, 16*8) 范围内生成一个随机位置并将相应位设置为 1。如果该位之前为零,那么您只是添加了一个位到数组。重复此操作,直到您添加了 n 位。

【讨论】:

    猜你喜欢
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-01-05
    • 2011-01-09
    • 1970-01-01
    • 2013-11-12
    • 2015-11-30
    • 2014-03-17
    相关资源
    最近更新 更多