Как сгенерировать n случайных единиц в массиве символов без знака в c / c ?

#c #c #random

#c #c #Случайный

Вопрос:

Это вопрос, отличный от того, который я только что задал, и он более сложный.

У меня есть массив символов без знака, скажем, unsigned char A[16] . Мне нужно сгенерировать вектор маски, который я применю к своему массиву A[16].

Он должен содержать n единиц, где 0 < n < 16 * 8 (вектор маски может быть массивом B[16], если в массиве n единиц)

Мне также нужно, чтобы эти n чисел ‘1 распределялись случайным образом в векторе.

Как я могу это сделать в c / c ?

Спасибо!

Редактировать: моя мысль заключается в следующем: я сгенерирую n случайных чисел (необходимо выполнить проверку, чтобы убедиться, что все n чисел не совпадают) и сохраню их в массиве tmp [n]. Затем маска генерируется на основе сдвига.

 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
  

Комментарии:

1. Вы довольно хорошо изложили свои требования, но не указали, что вы сделали, и каковы ваши идеи по решению этой проблемы. Это похоже на домашнее задание, и если вы не опубликуете свои усилия, это будет закрыто довольно скоро.

2. Это не домашнее задание … но я могу опубликовать свои усилия

Ответ №1:

Сгенерировать случайную (i,j) пару чисел, где i < 16 и j < 8 . Если бит в позиции B[i]amp;(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]amp;mask) == 0 ) {
            B[i] |= mask,   k;
        }
    }
}
  

Упражнение для задачи: удалите магическую константу 16 из кода.

Редактировать: модификация, предложенная в ваших комментариях, содержит неприятную ошибку. Вот тестовая программа, позволяющая воспроизвести способ распределения битов в вашей выходной маске.

 #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]amp;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) amp; 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;
        }
    }
}
  

Когда эта программа запускается, она пробует каждое значение n from 0 to 16*8 и генерирует случайную маску с n битами, затем проверяет, установлены ли именно n биты. Если возникает какая-либо ошибка (для некоторого значения n установлено несколько k!=n битов), выводится сообщение.

Если я изменю условие на if ( (B[i]^mask) != 0 ) , я получу последовательные ошибки в выходных данных. Каждый запуск выдает как минимум 1 сообщение об ошибке. Исходное условие if ( (B[i]amp;mask) == 0 ) последовательно выдает 0 сообщений об ошибках.

Комментарии:

1. Вам действительно нужен оператор запятой там?

2. Это должно быть j вместо (j-1) .

3. @K-ballo: Да. Это подчеркивает, что две инструкции на самом деле являются одним логическим шагом в алгоритме.

4. @ChristianRau: Спасибо, что заметили это.

5. Это не совсем то, что я хочу. Потому что, если n = 2, у меня может быть две единицы в B [0] . Если вы измените на if ( B[i]^mask != 0) . Тогда это работает.

Ответ №2:

У вас есть массив из 16 unsigned char секунд, который можно рассматривать как 16 * 8 бит. Чтобы сгенерировать случайную маску с n 1 битами в ней, сгенерируйте случайную позицию в диапазоне [0, 16 * 8) и установите соответствующий бит равным 1. Если бит ранее был равен нулю, значит, вы только что добавили бит в массив. Повторяйте это, пока не добавите n биты.