Вопрос

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

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?

Это было полезно?

Решение

Если вы используете C ++ и обеспокоены хорошим распределением, вы можете использовать TR1 C ++ 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;

Другие советы

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

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

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

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

Для объяснения Почему Метод наивный модуль плохие и почему вышеупомянутое лучше, обратитесь к отличной статье Жюльена о с использованием rand.

int rawRand = rand() % 101;

См. (Для более подробной информации):

RAND - C ++ Ссылка

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

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

РЕДАКТИРОВАТЬ

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

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

Ты можешь сделать

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-битными INT и использованием 100 чисел в качестве выхода, числа 0-16 представлены с 1,00000000000000000455 % от чисел (относительная точность идентично распределенной на 1 % на 10-18), в то время как числа 17-99 представлены с 0,9999999999999999913 % от чисел. Да, не идеально распределено, а очень хорошее приближение для небольших пролетов.

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

РЕДАКТИРОВАТЬ - Для людей, которые действительно заботятся о том, чтобы иметь равномерное распределение случайных чисел, работает следующий код. Обратите внимание, что это не обязательно оптимально, как при 64-битных случайных INT, это потребует двух вызовов rand() один раз каждые 10^18 звонков.

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;

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

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

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

Самым простым является преобразование, используя остаток при разделении на 101:

int value = rawRand % 101;

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

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

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

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

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

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

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

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

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

Rawrand % 101 даст [0-100], включительно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top