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

С++ генерирует случайные числа

Мой вывод 20 случайных 1, а не между 10 и 1, может ли кто-нибудь объяснить, почему это происходит?

#include <iostream> 
#include <ctime> 
#include <cstdlib>

using namespace std;

int main() 
{ 
    srand((unsigned)time(0)); 
    int random_integer; 
    int lowest=1, highest=10; 
    int range=(highest-lowest)+1; 
    for(int index=0; index<20; index++){ 
        random_integer = lowest+int(range*rand()/(RAND_MAX + 1.0)); 
        cout << random_integer << endl; 
    } 
}

Выход:     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1     1

4b9b3361

Ответ 1

Потому что на вашей платформе RAND_MAX == INT_MAX.

Выражение range*rand() никогда не может принимать значение больше, чем INT_MAX. Если математическое выражение больше, чем INT_MAX, то переполнение целых чисел уменьшает его до числа между INT_MIN и INT_MAX. Деление на RAND_MAX всегда будет равно нулю.

Попробуйте следующее выражение:

random_integer = lowest+int(range*(rand()/(RAND_MAX + 1.0)))

Ответ 2

Намного проще использовать библиотеку <random> правильно, чем rand (предполагая, что вы достаточно знакомы с С++, что синтаксис не бросает вас).

#include <random>
#include <iostream>

int main() {
  std::random_device r;
  std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
  std::mt19937 eng(seed);

  std::uniform_int_distribution<> dist(1, 10);

  for(int i = 0; i < 20; ++i)
    std::cout << dist(eng) << " ";
}

Ответ 3

random_integer = (rand() % 10) + 1 

Это должно дать вам псевдослучайное число от 1 до 10.

Ответ 4

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

Во-первых, конечно, проблема в исходном коде состоит в том, что range * rand() имеет приоритет над следующим подразделением и выполняется используя целочисленную арифметику. В зависимости от RAND_MAX это может легко приводят к переполнению, с реализацией определенных результатов; на все которые я знаю, если это приводит к переполнению (потому что RAND_MAX > INT_MAX / range, фактические результаты почти наверняка быть меньше, чем RAND_MAX + 1.0, а деление приведет к значение меньше 1.0. Существует несколько способов избежать этого: Простейшим и надежным является просто rand() % range + lowest.

Заметим, что это предполагает, что rand() имеет разумное качество. Многие прежних реализаций не было, и я видел, по крайней мере, один, где rand() % 6 + 1, чтобы имитировать бросок кубика чередующимся нечетным и четным. только правильное решение состоит в том, чтобы лучше реализовать rand(); это привело к тому, что люди пытались найти альтернативные решения, такие как (range * (rand() / (RAND_MAX + 1.0))) + lowest. Это маскирует проблема, но он не изменит плохой генератор в хороший.

Вторая проблема, , если важно качество генерации, является что при генерации случайных целых чисел вы дискретизируете: если вы например, для имитации броска кубика, у вас есть шесть возможных значения, которые вы хотите выполнить с равной вероятностью. Случайный генератор будет генерировать RAND_MAX + 1 разные значения, равные вероятность. Если RAND_MAX + 1 не кратно 6, то нет возможный способ распределения значений, равных значения. Представьте простой случай, когда RAND_MAX + 1 равно 10. Используя % выше, значения 1 & times; 4 в два раза больше, чем значения 5 и 6. Если вы используете более сложную формулу 1 + int(6 * (rand() / (RAND_MAX + 1.0))) (в случае, когда RAND_MAX + 1 == 10, оказывается, что 3 и 6 только наполовину вероятнее других. Математически нет возможности распространять 10 разных значения в 6 слотов с одинаковым количеством элементов в каждом слоте.

Конечно, RAND_MAX всегда будет значительно больше 10, и введенная предвзятость будет значительно меньше; если диапазон значительно меньше RAND_MAX, это может быть приемлемым. Если это не, однако, обычная процедура выглядит примерно так:

int limit = (RAND_MAX + 1LL) - (RAND_MAX + 1LL) % range;
            //  1LL will prevent overflow on most machines.
int result = rand();
while ( result >= limit ) {
    result = rand();
}
return result % range + lowest;

(Существует несколько способов определения значений для выброса. оказывается, тот, который я использую, но я помню, как Энди Кениг использовал что-то совершенно разные, но это привело к тому, что одни и те же значения были выкинутый в конце.)

Обратите внимание, что большую часть времени вы не будете вводить цикл; наихудший случай когда range есть (RAND_MAX + 1) / 2 + 1, и в этом случае вы все равно в среднем за один раз через цикл.

Обратите внимание, что эти комментарии применяются только тогда, когда вам необходимо фиксированное количество дискретные результаты. Для (другого) общего случая генерации случайного число с плавающей запятой в диапазоне [0,1), rand() / (RAND_MAX + 1.0) примерно так же хорошо, как вы собираетесь получить.

Ответ 5

Я предлагаю заменить rand()/(RAND_MAX + 1.0) на range*double(rand())/(RAND_MAX + 1.0)). Поскольку мое решение, похоже, дает головные боли...

возможные комбинации аргументов:

  • range*rand() является целым числом и переполняется.
  • double(range*rand()) переполняется, прежде чем преобразовать его в double.
  • range*double(rand()) не переполняется и дает ожидаемые результаты.

У моего первоначального сообщения было две фигурные скобки, но они ничего не меняли (результаты одинаковы).

Ответ 6

Visual studio 2008 вообще не имеет проблем с этой программой и с радостью генерирует swathe случайных чисел.

То, что я буду осторожен, это /(RAND_MAX +1.0), так как это, скорее всего, сменит целые проблемы и в конечном итоге с большим количеством жира.

Сбрасывать до двойного значения перед делением, а затем отбрасывать обратно в int

Ответ 7

(rand() % highest) + lowest + 1

Ответ 8

Вы генерируете случайное число (т.е. (range*rand()/(RAND_MAX + 1.0))), значение которого находится между -1 и 1 (]-1,1[), а затем отбрасывает его на целое число. Целочисленное значение такого числа всегда равно 0, поэтому вы заканчиваете с lower + 0

EDIT: добавила формулу, чтобы сделать мой ответ более ясным

Ответ 9

Вероятно, "10 * rand()" меньше, чем "RAND_MAX + 1.0", поэтому значение вашего вычисления равно 0.

Ответ 10

Это одна из самых простых логик, полученная из блога. в этой логике вы можете ограничить случайные числа с помощью данного заданного оператора модуля (%) внутри цикла for, просто скопируйте и вставьте из этого блога, но в любом случае проверьте это:

// random numbers generation in C++ using builtin functions
#include <iostream>

using namespace std;

#include <iomanip>

using std::setw;

#include <cstdlib>   // contains function prototype for rand

int main()
{
// loop 20 times
for ( int counter = 1; counter <= 20; counter++ ) {

    // pick random number from 1 to 6 and output it
    cout << setw( 10 ) << ( 1 + rand() % 6 );

    // if counter divisible by 5, begin new line of output
    if ( counter % 5 == 0 )
        cout << endl;

}

return 0;  // indicates successful termination

} // end main

- Подробнее на: http://www.programmingtunes.com/generation-of-random-numbers-c/#sthash.BTZoT5ot.dpuf

Ответ 11

Как использовать условие, чтобы проверить, совпадает ли последний номер с текущим? Если условие выполнено, сгенерируйте другое случайное число. Это решение работает, но потребуется больше времени.