Подтвердить что ты не робот

Как уменьшить числа из rand()?

Следующий код выводит случайное число каждую секунду:

int main ()
{
    srand(time(NULL)); // Seeds number generator with execution time.

    while (true)
    {
        int rawRand = rand();

        std::cout << rawRand << std::endl;

        sleep(1);
    }
}

Как я могу уменьшить эти числа, чтобы они всегда находились в диапазоне 0-100?

4b9b3361

Ответ 1

Если вы используете С++ и обеспокоены хорошим распределением, вы можете использовать TR1 С++ 11 <random>.

#include <random>

std::random_device rseed;
std::mt19937 rgen(rseed()); // mersenne_twister
std::uniform_int_distribution<int> idist(0,100); // [0,100]

std::cout << idist(rgen) << std::endl;

Ответ 2

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

Лучшим способом генерации реального равномерного распределения случайных чисел в любом диапазоне [0, N] является следующее (предполагая, что rand фактически следует равномерному распределению, что далеко не очевидно):

unsigned result;
do {
    result = rand();
} while (result > N);

Конечно, этот метод медленный, но он дает хорошее распределение. Немного более разумный способ сделать это - найти наибольшее кратное N, которое меньше, чем RAND_MAX, и использовать это как верхнюю границу. После этого можно спокойно взять result % (N + 1).

Для объяснения, почему метод наивного модуля плох и почему выше это лучше, ссылайтесь на статью Juliennes на с помощью rand.

Ответ 3

int rawRand = rand() % 101;

См. (для получения дополнительной информации):

rand - ссылка на С++

Другие также отметили, что это не даст вам наилучшего распределения случайных чисел. Если это важно в вашем коде, вам нужно будет:

int rawRand = (rand() * 1.0 / RAND_MAX) * 100;

Забастовкa >

ИЗМЕНИТЬ

Через три года я делаю редактирование. Как уже упоминалось, rand() имеет много проблем. Очевидно, я не могу рекомендовать его использование, когда есть лучшие альтернативы в будущем. Вы можете прочитать все подробности и рекомендации здесь:

rand() считается вредным | GoingNative 2013

Ответ 4

См. man 3 rand - вам нужно масштабировать, делясь на RAND_MAX, чтобы получить диапазон [0, 1], после которого вы можете умножить на 100 для вашего целевого диапазона.

Ответ 5

Вы можете сделать

cout << rawRand % 100 << endl; // Outputs between 0 and 99

cout << rawRand % 101 << endl; // outputs between 0 and 100

Для людей вниз; заметьте одну минуту после того, как это было изначально опубликовано. Я оставил комментарий:

Из http://www.cplusplus.com/reference/clibrary/cstdlib/rand "Обратите внимание, что эта модульная операция не генерирует по-настоящему равномерно распределенное случайное число в промежутке (поскольку в большинстве случаев более низкие цифры немного более вероятны), но, как правило, это хорошее приближение для коротких промежутков".

С 64-битным ints и использованием 100 чисел в качестве вывода числа 0-16 представлены с 1.00000000000000000455% от числа (относительная точность для одинакового распределения 1% примерно на 10 -18), а числа 17-99 представлены с 0.99999999999999999913% от числа. Да, не совсем распределено, но очень хорошее приближение для небольших промежутков.

Также обратите внимание, где OP запрашивает одинаково распределенные номера? Для всех, кого мы знаем, они используются для целей, когда небольшие отклонения не имеют значения (например, ничего, кроме криптографии), и если они используют числа для криптографии, этот вопрос слишком наивна для того, чтобы они писали свою собственную криптографию).

EDIT. Для людей, которые действительно заинтересованы в равномерном распределении случайных чисел, работает следующий код. Обратите внимание, что это не обязательно оптимально, как и для 64-битных случайных ints, для каждого вызова 10 ^ 18 потребуется два вызова rand().

unsigned N = 100; // want numbers 0-99
unsigned long randTruncation = (RAND_MAX / N) * N; 
// include every number the N times by ensuring rawRand is between 0 and randTruncation - 1 or regenerate.
unsigned long rawRand = rand();

while (rawRand >= randTruncation) {
    rawRand = rand();  
// with 64-bit int and range of 0-99 will need to generate two random numbers
// about 1 in every (2^63)/16 ~ 10^18 times (1 million million times)

// with 32-bit int and range of 0-99 will need to generate two random numbers 
// once every 46 million times.

}
cout << rawRand % N << stdl::endl;

Ответ 6

В диапазоне от min до max (включительно) используйте: int result = rand() % (max - min + 1) + min;

Ответ 7

rawRand% 101 дал бы [0-100] включительно.

Ответ 8

Как долго ответ вы хотели бы.

простейшим является преобразование с использованием остатка при делении на 101:

int value = rawRand % 101;

Полупуритель будет перемасштабировать с использованием удвоений:

double dbl = 100 * ((double)rawRand / RAND_MAX);
int ivalue = (int)(dbl + 0.5);   // round up for above 0.5

И пурист скажет, что ранд не производит случайных чисел.

Для вашей информации качество случайных чисел измеряется путем принятия последовательности чисел, а затем вычисления математической вероятности того, что источник этой последовательности был случайным. Простой взлом с использованием остатка - очень плохой выбор, если вы после случайности.

Ответ 9

Некоторые люди разместили в качестве примера следующий код:

int rawRand = (rand() / RAND_MAX) * 100;

Это недопустимый способ решения проблемы, поскольку и rand(), и RAND_MAX являются целыми числами. В С++ это приводит к интегральному делению, которое усекает десятичные точки результатов. Поскольку RAND_MAX >= rand(), результатом этой операции является либо 1, либо 0, то есть rawRand может быть только 0 или 100. Правильный способ сделать это будет следующим:

int rawRand = (rand() / static_cast<double>(RAND_MAX)) * 100;

Поскольку один из операндов теперь является двойным, используется деление с плавающей запятой, которое возвращает правильное значение между 0 и 1.