Как я могу избавиться от предупреждения с помощью rand ()? (C ++) - PullRequest
1 голос
/ 04 мая 2009

Всякий раз, когда я использую функцию rand в C ++:

#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
int main(){
srand(time(0));
int n=(rand()%6)+1;
cout<<"The dice roll is "<<n<<"."<<endl;
}

Я получаю предупреждение о преобразовании из time_t в int в строке 5:

srand(time(0));

Есть ли способ избавиться от этого предупреждения?

Ответы [ 6 ]

8 голосов
/ 04 мая 2009

На самом деле, вы должны использовать без знака int с srand () :

srand((unsigned) time(0));
6 голосов
/ 04 мая 2009

На другой ноте этот код:

rand()%6

обычно считается плохой практикой. младшие биты rand () значительно менее случайны, чем старшие биты. Вы получите лучшую случайность, если сделаете:

(rand() >> 8)%6

например.

EDIT:

Подробнее об этом см. в этой заметке , а также в статье Dr. Журнал Доббса , который хотя бы намекает на причину:

Примечание: НЕ использовать

  y = rand()  %  M;

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

DDJ:

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

Например, если вы хотите выбрать случайное «истинное» или «ложное» значение, и вы использовали код:

rand() % 2

Тогда вы можете увидеть шаблон результатов:

1,0,1,0,1,0,1,0,1,0 (и т. Д.)

Это, очевидно, не так уж случайно, но это свойство линейного конгруэнтного генератора, которое может использоваться. В целом, лучшая схема (для C ++) может заключаться в использовании библиотеки Boost.Random , которая поддерживает все виды подключаемых случайных генераторов (включая Mersenne Twister, у которого нет этой ошибки).

2 голосов
/ 04 мая 2009

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

srand(static_cast<unsigned int>(time(0)));

На соответствующей ноте результаты rand должны быть сдвинуты вправо, чтобы устранить смещение в младших битах.

int n = ((rand() >> 8) % 6) + 1;

Наконец, в C ++ время C и стандартные библиотеки должны быть включены как:

#include <ctime>
#include <cstdlib>

Это поместит функции в соответствующее пространство имен 'std'.

2 голосов
/ 04 мая 2009

Два примечания:

  • Стандартный способ включения заголовков C в C ++ выглядит так: #include <cstdio>.
  • Параметр, переданный time(), является указателем, и многие считают, что NULL является более читаемым нулевым указателем, чем 0.
2 голосов
/ 04 мая 2009

Используйте явное приведение, чтобы избавиться от предупреждения:

srand((int)time(0));
1 голос
/ 04 мая 2009

Кроме того,

 rand() % 6

введет небольшой уклон. Так как RAND_MAX% 6 равен 1, ноль и единица будут появляться немного чаще, чем два-шесть. В этом случае они возвращаются 5462 раза за каждые 5461 раз, когда возвращаются старшие числа, так что вы, вероятно, не заметите этого. Однако, если диапазон чисел, который вы хотите, велик, смещение может быть значительным. Например, если вы сделали rand() % 32000, то число в диапазоне 0–767 увеличилось бы вдвое чаще, чем эти 768–32000.

...