C++. Генератор вещественных случайных чисел

Модератор: Модераторы разделов

vipermagi
Сообщения: 83
ОС: AgiliaLinux

C++. Генератор вещественных случайных чисел

Сообщение vipermagi »

На входе функции: одна граница интервала, другая граница интервала. На выходе, собственно, случайное вещественное число из этого интервала.

Для целых чисел вот как-то так:

Код: Выделить всё

int randInt(int from, int to)
    {

    int low=from, high=to;
    if(from>to)
    {
    low = to;
    high = from;
    }

    return qrand() % ((high + 1) - low) + low;
    }


А вот как по-человечески сгенерить дробное число, мне не очень на ум приходит. Первая мысль - как-то умножить числа границ до целых, потом передать их в randInt и разделить результат обратно до вещественного.

Есть мысль как это сделать правильно? А то даже, говорят, использование % для масштабирования не есть правильно, почему-то. В общем, хочется мне качественно разрешить для себя данный вопрос.
Спасибо сказали:
allez
Сообщения: 2223
Статус: Не очень злой админ :-)
ОС: SuSE, CentOS, FreeBSD, Windows

Re: C++. Генератор вещественных случайных чисел

Сообщение allez »

vipermagi писал(а):
09.03.2014 15:06
А вот как по-человечески сгенерить дробное число, мне не очень на ум приходит. Первая мысль - как-то умножить числа границ до целых, потом передать их в randInt и разделить результат обратно до вещественного.
На мой взгляд - способ, вполне имеющий право на существование.

В порядке прикола могу предложить такой способ:

1. Генерируем целое число в интервале от from до to - 1.
2. Генерируем целое число в интервале от 0 до 999 (если нужна точность до тысячных).
3. Преобразуем полученные числа в строки.
4. Объединяем эти строки в одну, разделив их символом десятичной дроби.
5. Преобразуем полученную строку в вещественное число.

Ну, как вам алгорЫтм? :)
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C++. Генератор вещественных случайных чисел

Сообщение NickLion »

allez
Можно гораздо проще.

1. Похож на тот, что Вы предложили, только без лишних манипуляций: сгенерировать от 1000*from до 1000*to - 1, а потом разделить на 1000.0: (rand() % ((to - from) * 1000)) / 1000.0

2. (rand() / (double)RAND_MAX) * (to - from) + from

UPD уточнение, первый способ даёт ограниченную десятичную точность (3 знака в данном случае), но иногда полезен. Точность второго размазана по всему диапазону, даёт длинный хвост.

И да, RAND_MAX может различаться для разных платформ, для MS VC++ = 65535, а для GCC = 2147483647
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: C++. Генератор вещественных случайных чисел

Сообщение eddy »

Код: Выделить всё

man drand48

Я с его помощью и сложные функции распределения делал (при помощи обратных функций).
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C++. Генератор вещественных случайных чисел

Сообщение drBatty »

vipermagi
1. всё уже придумано до нас. У Кнута на эту тему многобукв.
2. Практически все нормальные генераторы(у Кнуута есть примеры) генерируют число от 0 до M (большое. Обычно 2³²-1 или типа того). С более-менее равномерным распределением. Что-бы получить число от 0 до 1 надо просто поделить на это M.
3. Остальные распределения делаются из равномерного просто свёрткой с функцией. (нормальное распределение можно получить также взяв Over9000 обычных числел и сложив. Оно всё равно только в лабах нужно(IRL оно само собой получается))
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: C++. Генератор вещественных случайных чисел

Сообщение drBatty »

vipermagi писал(а):
09.03.2014 15:06
А то даже, говорят, использование % для масштабирования не есть правильно, почему-то

дык это жеж деление. Оно долгое. Ещё и опасное тем, что можно на ноль поделить. Используйте умножение. В целых оно всё равно по модулю M. И намного быстрее.

PS: что-бы получить например число от 0 до 7 надо умножить на 7*M а потом поделить на M(второе действие в x86 это тупо другой регистр(edx), потому бесплатное)
PPS: асм не нужен, компилятор обычно сам поймёт, что вы имели ввиду.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: