Random
Попробуй так:
int((float(rand())/float(RAND_MAX))*1000.0f)
А почему случайные числа должны быть расположены равномерно? Они ведь случайные.
И к чему вся эта туфта с флоатом. Первый вариант нормально работает...
On 2002-10-02 0225, AL C++ Programmer wrote
Не совсем так... При rand()%1000 случайные числа не будут распределены равномерно.
Попробуй так
int((float(rand())/float(RAND_MAX))*1000.0f)
Еще раз посмотрел твое сообщение ))
Ну ты даешь!!! такое написать!!!
On 2002-10-01 2243, quasar1983 wrote
int x=rand()%1000;
На самом деле здесь будут случайные числа от 0 до 999 так как %1000 - означает взятие по модулю от 1000. Т.е. 1000%1000= 0.
правильней было бы использовать
int x = rand() % 1001;
И еще...
для того чтобы при каждом запуске числа не повторялись нужно привязать начальное значение к дате-времени функцией
srand((unsigned) time(NULL));
Мда... Я разве сказал "расположены"?
Равномерное распределение, термин из теории вероятностей
означающий, что любой элемент из множества {0, 1, ... n-1}
может быть выбран с вероятностью 1/n
>> И к чему вся эта туфта с флоатом. Первый вариант нормально работает...
Ты проверял?
Рассмотрим пример:
int x=rand()%10000
rand() возвращает псевдослучайное число от 0 до 32677.
В x окажется число 2768-9999 если rand() вернет:
2768-9999; 12768-19999; 22768-29999 итого 21696 из 32768;
21696/32768 = 0.662109375 а доля чисел 2678-9999 составляет 0.7322 от 10000
В x окажется число 0-2677 если rand() вернет
0-2767; 10000-12767; 20000-22767; 30000-32767 итого 11072 из 32768;
11072/32768 = 0.337890625, а доля чисел 0-2677 составляет 0.2678 от 10000
Вот так-то.
Впрочем, "нормально" понятие относительное, и кого-то такой расклад вполне устраивает...
Так же прошу заметить что я прежде всего Programmer а уже потом C++ Programmer
С уважением, AL C++ Programmer.
А почему случайные числа должны быть расположены равномерно? Они ведь случайные.
И к чему вся эта туфта с флоатом. Первый вариант нормально работает...
если распределение "случайных" чисел не равномерное, то это уже не совсем "случайные" в понятии обычного человека (хотя в теорвере исследованы множество распределений имеющих практическую ценность нормальное, пуассона, стьюдента, равномерное, и пр).
Дык вот когда события не совсем случайные, это иногда может сильно мешать. Хотя есть системы где события не равномерны, скажем в СМО (системах массового обслуживания) поток заявок обычно имеет Пуассоновское распределение.
Скажем ты делаешь какую-нить игру, у тебя события которые должны были быть равнозначными станут предопределёнными.
а с float иногда тоже имеет смысл заморочится, простой пример, делаем подобие салюта, задача из точки A(x,y) должны вылететь N пикселей в разные стороны, и потом под действием гравитации упасть на "землю".
На ум приходит
struct particle{
. int x,y;
. int dx,dy;
};
particle g_particles[N];
const max_speed = 13;
const gravity = 1;
void InitBoom(int x, int y)
{
. particle *p = g_particles;
. for (int i=0; i<N; i++, p++)
. {
. p->x = x;
. p->y = y;
. // dx от -6 до 6
. p->dx = max_speed/2 - rand() % max_speed;
. // dy от -6 до 6
. p->dy = max_speed/2 - rand() % max_speed;
. }
}
void MoveParticles()
{
. particle *p = g_particles;
. for (int i=0; i<N; i++, p++)
. {
. p->x += p->dx;
. p->y += p->dy;
. // тут мы проверям на столкновение с краями экрана
.
. if (p->x < 0)
. {
. p->x-=p->dx;
. p->dx=-p->dx;
. }
. // ну и так далее со всеми краями, опускаю, тк это не интересно
. //. ..........
....................
. увеличиваем скорость вниз, как бы под действием гравитации
. p->dy+=gravity;
. }
}
void DrawParticles()
{
. particle *p = g_particles;
. for (int i=0; i<N; i++, p++)
. {
. PutPixel(p->x, p->y);
. }
}
void main()
{
. InitBoom(rand() % 320, rand() % 200);
. SetMode(0x13);
. do{
. DrawParticles();
. MoveParticles();
. if (kbhit())
. {
. if (getch()==' ') InitBoom(rand() % 320, rand() % 200);
. else break;
. }
. }while(1);
. SetMode(0x03);
}
вот я опустин несущественные детали допустил какие-то ошибки, но я думаю идея понятна.
Дык очём это я, ах вот так если мы посмотрим на то как двигаются эти пиксели, то увидим что на салют они мало похожи, т.к. разлетаются, они квадратом, а не кругом.
Чтобы стало всё ок надо изменить структуру particle и InitBoom()
struct particle{
. float x,y,dx,dy; // дробные числа на обеспечат плавное движение
};
void InitBoom(int x, int y)
{
. particle *p = g_particles;
. for (int i=0; i<N; i++, p++)
. {
. p->x = x;
. p->y = y;
. берём "псевдослучайный" угол в радианах
. float angle = 3.1415 * 2 * (float)rand()/RAND_MAX;
. а это вектор направления
. // dx от ~-6.0 до ~6.0
. p->dx = (float)sin(angle) * max_speed/2;
. // dy от ~-6.0 до ~6.0
. p->dy = (float)cos(angle) * max_speed/2;
. }
}
а при рисовании округляем координаты
PutPixel((int)floor(p->x+.5), (int)floor(p->y+.5));
>> А почему случайные числа должны быть расположены равномерно?
Мда... Я разве сказал "расположены"?
Равномерное распределение, термин из теории вероятностей
означающий, что любой элемент из множества {0, 1, ... n-1}
может быть выбран с вероятностью 1/n
>> И к чему вся эта туфта с флоатом. Первый вариант нормально работает...
Ты проверял?
Рассмотрим пример:
int x=rand()%10000
rand() возвращает псевдослучайное число от 0 до 32677.
В x окажется число 2768-9999 если rand() вернет:
2768-9999; 12768-19999; 22768-29999 итого 21696 из 32768;
21696/32768 = 0.662109375 а доля чисел 2678-9999 составляет 0.7322 от 10000
В x окажется число 0-2677 если rand() вернет
0-2767; 10000-12767; 20000-22767; 30000-32767 итого 11072 из 32768;
11072/32768 = 0.337890625, а доля чисел 0-2677 составляет 0.2678 от 10000
Вот так-то.
Впрочем, "нормально" понятие относительное, и кого-то такой расклад вполне устраивает...
Так же прошу заметить что я прежде всего Programmer а уже потом C++ Programmer
С уважением, AL C++ Programmer.
Что-то ты перемудрил. Функция rand() возвращает псевдослучайное число от 0 до RAND_MAX при любом раскладе. А потом ты делишь это по модулю на 1000. И получаешь теже числа но в сжатом диапазоне. И все таки ты туфту нагнал. Проверь у себя ошибки, почитай Кнута.
P.S. RAND_MAX не всегда равно 2^16
Что-то ты перемудрил. Функция rand() возвращает псевдослучайное число от 0 до RAND_MAX при любом раскладе. А потом ты делишь это по модулю на 1000. И получаешь теже числа но в сжатом диапазоне. И все таки ты туфту нагнал. Проверь у себя ошибки, почитай Кнута.
P.S. RAND_MAX не всегда равно 2^16
Укажи мне пожалуйста хоть на одну мою ошибку.
Я знаю, что RAND_MAX не всегда равно 2^16-1, но это не важно...
Важно то, что (rand() % x) будет равномерно распределенной последовательностью случайных чисел только при RAND_MAX кратном x. Т.е. например если x==1000, то RAND_MAX должно быть равно 30000 или 40000, не важно. В противном случае (например, с теми же 32678) вот эти самые 2678 и дают дополнительнуй вероятность выпадения чисел 1-2678...
Т.е. числа 1-2678 будут встерчаться чаще, чем 2679-9999 и 0.
Вариант с флоатом от таких недочетов избавлен.
Простейший вариант проверки - сгенерить 100000 чисел твоим и моим способом и вычислить среднее. С флоатом среднее будет ближе к 5000, а с % ближе к 2678.
P.S. После твоего ответа я специально посмотрел Кнута, на всякий случай, а вдруг я правда ошибся. Хммм... Нет, все правильно.
Укажи мне пожалуйста хоть на одну мою ошибку.
Я знаю, что RAND_MAX не всегда равно 2^16-1, но это не важно...
Важно то, что (rand() % x) будет равномерно распределенной последовательностью случайных чисел только при RAND_MAX кратном x. Т.е. например если x==1000, то RAND_MAX должно быть равно 30000 или 40000, не важно. В противном случае (например, с теми же 32678) вот эти самые 2678 и дают дополнительнуй вероятность выпадения чисел 1-2678...
Т.е. числа 1-2678 будут встерчаться чаще, чем 2679-9999 и 0.
Вариант с флоатом от таких недочетов избавлен.
Простейший вариант проверки - сгенерить 100000 чисел твоим и моим способом и вычислить среднее. С флоатом среднее будет ближе к 5000, а с % ближе к 2678.
P.S. После твоего ответа я специально посмотрел Кнута, на всякий случай, а вдруг я правда ошибся. Хммм... Нет, все правильно.
Да результаты действительно такие. Но не так сильно отклонение:
(С флоатом среднее будет ближе к 5000, а с % ближе к 2678)
4948.32 - с флоатом
4641.69 - с %
Но для большинства задач наверно подойдет и целочисленный вариант.
А лучше самому написать ГСЧ.
Как присвоить переменной (int) значение random, те. случайное число, между 0 и 1000
В целых числах можно сделать так:
int RandomValue = rand()*1000/RAND_MAX
Но это справедливо только, если RAND_MAX*1000 не вызывает переполнения int.
Можно еще так:
int RandomValue = (int)(((long)rand())*1000/RAND_MAX)
В целых числах можно сделать так:
int RandomValue = rand()*1000/RAND_MAX
Но это справедливо только, если RAND_MAX*1000 не вызывает переполнения int.
Можно еще так:
int RandomValue = (int)(((long)rand())*1000/RAND_MAX)
Ты читал то что выше?
Ты читал то что выше?
Конечно. Но способ rand()%1000 мне однозначно не нравится по приведенным выше причинам. Или я что-то пропустил ?
СПАСИБО ВСЕМ!!!!
зы если нечего не получится я напишу.
-=ZATCH=-
[zatch@mail.ru]
тогда и я приму участие:
- никто не гарантирует что rand() сам по себе генерирует случайное число с равномерным распределением..... он тока гарантирует что оно будет псевдослучайным :) и все....
- при выборке 1000000 мат ожидание:
rand()%1000 - ~497
(float) ля-ля ля - ~499
- если надо "просто случайное число" то rand()%1000 вполне подходит...
- если нужна математически точное нормальное распределение то можно побаловаться и с float.. есть еще более точные алгоритмы использующие несколько значений полученных при помощи rand()... а можно свой алгоритм написать (так например сделано в пакетах a-la MathCad)