Генерация случайных чисел по нормальному закону распределения
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 27.11.20 08:44
Оценка: -1 :)))
Как в C++ сгенерировать случайные числа по нормальному закону распределения?
Есть ли какие-нибудь библиотечные функции для генерирования случайных чисел по нормальному закону распределения?
Если нет таких библиотечных функций, то как это сделать?
1613 г. = 2024 г.
Re: Генерация случайных чисел по нормальному закону распределения
От: watchmaker  
Дата: 27.11.20 08:55
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как в C++ сгенерировать случайные числа по нормальному закону распределения?


std::normal_distribution
Re: Генерация случайных чисел по нормальному закону распределения
От: Chorkov Россия  
Дата: 27.11.20 08:59
Оценка: +1
Здравствуйте, RussianFellow, Вы писали:

RF>Как в C++ сгенерировать случайные числа по нормальному закону распределения?

RF>Есть ли какие-нибудь библиотечные функции для генерирования случайных чисел по нормальному закону распределения?
RF>Если нет таких библиотечных функций, то как это сделать?

C++11 : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution
Если C++11 недоступен, то boost.

Если интересует, как задача генерации случайных чисел по заданному распределению решается в общем виде — см. "производящая функция".
К сожалению, интеграл функции ошибок (erf), тоже появились в с++11.
Re: Генерация случайных чисел по нормальному закону распреде
От: kov_serg Россия  
Дата: 27.11.20 09:15
Оценка: 2 (1)
Здравствуйте, RussianFellow, Вы писали:

RF>Как в C++ сгенерировать случайные числа по нормальному закону распределения?

RF>Есть ли какие-нибудь библиотечные функции для генерирования случайных чисел по нормальному закону распределения?
RF>Если нет таких библиотечных функций, то как это сделать?
Элементарно: вот код на lua
function normal() 
  local a,b=math.random(),math.random()
  return 
    math.sqrt(-2*math.log(a))*math.cos(2*math.pi*b),
    math.sqrt(-2*math.log(b))*math.sin(2*math.pi*a)
end
Эта функция возвращает пару чисел распределенных по нормальному закону
Отредактировано 27.11.2020 9:33 kov_serg . Предыдущая версия . Еще …
Отредактировано 27.11.2020 9:31 kov_serg . Предыдущая версия .
Отредактировано 27.11.2020 9:16 kov_serg . Предыдущая версия .
Re[2]: Генерация случайных чисел по нормальному закону распределения
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 27.11.20 10:18
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>C++11 : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution

C>Если C++11 недоступен, то boost.

А начиная с какой версии Visual Studio доступен C++11 ?
1613 г. = 2024 г.
Re[2]: Генерация случайных чисел по нормальному закону распределения
От: Шахтер Интернет  
Дата: 27.11.20 17:48
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Здравствуйте, RussianFellow, Вы писали:


RF>>Как в C++ сгенерировать случайные числа по нормальному закону распределения?

RF>>Есть ли какие-нибудь библиотечные функции для генерирования случайных чисел по нормальному закону распределения?
RF>>Если нет таких библиотечных функций, то как это сделать?

C>C++11 : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution

C>Если C++11 недоступен, то boost.

C>Если интересует, как задача генерации случайных чисел по заданному распределению решается в общем виде — см. "производящая функция".

C>К сожалению, интеграл функции ошибок (erf), тоже появились в с++11.

А написать реализацию его вычисления 99% современных программистов не способны.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Генерация случайных чисел по нормальному закону распределения
От: SaZ  
Дата: 27.11.20 22:19
Оценка: +1 :))) :)
Здравствуйте, RussianFellow, Вы писали:

RF>Здравствуйте, Chorkov, Вы писали:


C>>C++11 : https://en.cppreference.com/w/cpp/numeric/random/normal_distribution

C>>Если C++11 недоступен, то boost.

RF>А начиная с какой версии Visual Studio доступен C++11 ?


По первой ссылке в гугле, ту что сможете скачать и поставить.

P.S. С удовольствием читаю ваши вопросы. Мне вот интересно, у вас есть хотя-бы один завершённый коммерческий проект? Не обязательно свой, пойдёт и работа обычным программистом. Просто вы уже много лет задаёте странные вопросы, в том числе которые элементарно гуглятся.
Re[3]: Генерация случайных чисел по нормальному закону распределения
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 30.11.20 10:05
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>А написать реализацию его вычисления 99% современных программистов не способны.

Да я думаю вспомнить что такое нормально распределение и что оно распределяет не смогут 60% программистов =\
Sic luceat lux!
Re: Генерация случайных чисел по нормальному закону распреде
От: TailWind  
Дата: 30.11.20 20:24
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Как в C++ сгенерировать случайные числа по нормальному закону распределения?

Биномиальное распределение при больших N приближается к нормальному
Треугольник Паскаля тоже

Их легко реализовать, главное переполнение контролировать

int q=0; repeat (1000) if (rand() & 1) q++;
Отредактировано 30.11.2020 20:29 TailWind . Предыдущая версия .
Re: Генерация случайных чисел по нормальному закону распреде
От: Максим Россия  
Дата: 16.12.20 07:28
Оценка:
RF>Если нет таких библиотечных функций, то как это сделать?

Обычно, все сложные распределения моделируются через равномерно распределенные случайные величины (а их моделировать достаточно просто). Для нормального распределения можно применить Преобразование Бокса-Мюллера. Это, думаю, самый простой способ. Код на ЛУА kov_serg привел выше

https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%BE%D0%BA%D1%81%D0%B0_%E2%80%94_%D0%9C%D1%8E%D0%BB%D0%BB%D0%B5%D1%80%D0%B0

У меня когда-то даже спецкурс был на эту тему... Вот ссылка на лекции если интересно http://statmod.ru/wiki/_media/books:vv:simulation_v4.pdf
Errare humanum est
Отредактировано 16.12.2020 7:30 Максим . Предыдущая версия .
Re[4]: [OFF] Извините, но про нормальность вы не правы
От: Mystic Artifact  
Дата: 16.12.20 23:05
Оценка:
Здравствуйте, Kernan, Вы писали:

Ш>>А написать реализацию его вычисления 99% современных программистов не способны.

K>Да я думаю вспомнить что такое нормально распределение и что оно распределяет не смогут 60% программистов =\

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

Нормальное же распределение получило своё имя совершенно неоправданно, потому, что никоим образом данное распределение в человеческом мозгу нормальным считаться не может (ну может конечно — у упоротых математикой на голову).

А программисты, кто вообще слышал о функции Гаусса, либо о колоколо-образном распределении, либо кто с этим сталкивался, безусловно смогут его реализовать с необходимыми характеристиками. В добавок математически-правильное распределение тоже нужно далеко не всегда, на практике можно увидеть необходимость генерации случайного числа по заданной форме "колокола" (bell-shape), при чем никакими "нормальными" формулами её разумеется никто описывать не будет, т.к. в нормальном софте — пользователь задаёт саму кривую а не какие-то там формулы.

Поэтому рассказы про то что там не умеют 60% это такое себе занятие, и нытье по вещам о которых слушал в университете N десятков лет назад — мягко говоря странны. Те кто слышал и в курсе — при необходимости, даже если забыли — подымут нужную информацию за 5 минут. Те кто не в курсе терминологии видимо не программисты и не математики по образованию, и возможно им неведом раздел статистики вообще — но так и механики же нам прощают, когда мы ебалду называем ****ой, вместо лонжерона, ляды и прочих куда более заковыристых терминов?
Re[2]: Генерация случайных чисел по нормальному закону распреде
От: TailWind  
Дата: 17.12.20 09:10
Оценка: 9 (1)
У этой формулы есть проблема

Она справедлива, если на вход подают непрерывную случайную величину

rand() в C++ возвращает дискретные значения

Соответственно на выходе у вас получится, тоже дискретное распределение

Но если у rand(), на графике плотности вероятности отметки по оси X шли с одним и тем же шагом

То у полученного нормального распределения, отметки по оси Х будут уже идти с переменным шагом

Что не клёво, если вы хотите строить графики или проверять статистические теоремы

_>Элементарно: вот код на lua

_>
_>function normal() 
_>  local a,b=math.random(),math.random()
_>  return 
_>    math.sqrt(-2*math.log(a))*math.cos(2*math.pi*b),
_>    math.sqrt(-2*math.log(b))*math.sin(2*math.pi*a)
_>end
_>
Эта функция возвращает пару чисел распределенных по нормальному закону
Re[3]: Генерация случайных чисел по нормальному закону распреде
От: kov_serg Россия  
Дата: 17.12.20 10:50
Оценка:
Здравствуйте, TailWind, Вы писали:

TW>У этой формулы есть проблема

У реализации может быть, но алгоритм не причем.
TW>Она справедлива, если на вход подают непрерывную случайную величину
TW>rand() в C++ возвращает дискретные значения
так непрерывные значения мы моделируем дискретными, если не хватает то увеличиваем разрядность.
rand — 15bit => 4*15=60 что больше чем 52бита мантисы double
double uniform_random() {
    double r=0;
    for(int i=0;i<4;i++) r=(r+rand())/(RAND_MAX+1.0);
    return r;
}

Это проблема конкретной реализации. Замените rand на более православный генератор.
И вообще в c++ есть сразу готовые библиотеки для нормального распределения.

TW>Соответственно на выходе у вас получится, тоже дискретное распределение

И что вас смущает. Выбирайте рабочие диапазоны где это не критично. Не используйте дальние хвосты.
Или возьмите проверенные варианты: https://www.netlib.org/random/index.html
Re[3]: Генерация случайных чисел по нормальному закону распр
От: watchmaker  
Дата: 17.12.20 11:47
Оценка: 9 (1)
Здравствуйте, TailWind, Вы писали:

_>>Элементарно: вот код на lua

_>>
_>>function normal() 
_>>  local a,b=math.random(),math.random()
_>>  return 
_>>    math.sqrt(-2*math.log(a))*math.cos(2*math.pi*b),
_>>    math.sqrt(-2*math.log(b))*math.sin(2*math.pi*a)
_>>end
_>>
Эта функция возвращает пару чисел распределенных по нормальному закону

TW>У этой формулы есть проблема
TW>Она справедлива, если на вход подают непрерывную случайную величину
TW>Что не клёво, если вы хотите строить графики или проверять статистические теоремы

LOL. Если вы придрались к этому аспекту, то у вас явная проблема в приоритетах

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


Слева миллион точек полученных вызовом numpy.random.normal. А справа вариант, генерируемый функцией за авторством kov_serg.
Правда ведь правый вариант выглядит немного не похожим на нормальное распределение?


То есть проблема функции в том, что она хотя и генерирует числа с нормальным распределением, но даёт независимость только y отдельных компонент (только у первых чисел из пары или только у вторых), а всё множество не независимо.
Это примерно как если сгенерировать последовательность из чисел U = [uniform_random()]. Она случайная и элементы независимы. И последовательность чисел V = [(1 — x) for x in U] тоже случайная и в ней тоже элементы независимы. Но объединение последовательностей U и V уже не будет обладать таким свойством.
Отредактировано 17.12.2020 19:51 watchmaker . Предыдущая версия . Еще …
Отредактировано 17.12.2020 19:45 watchmaker . Предыдущая версия .
Re[4]: Генерация случайных чисел по нормальному закону распреде
От: kov_serg Россия  
Дата: 17.12.20 12:03
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Слева вариант по формулам из википедии. А справа вариант, генерируемый функцией за авторством kov_serg.

W>Правда ведь правый вариант выглядит немного не похожим на нормальное распределение?
Да косяк.
function normal() 
    local a=math.sqrt(-2*math.log(math.random()))
    local b=2*math.pi*math.random()
    return a*math.cos(b), a*math.sin(b)
end
Re[5]: Генерация случайных чисел по нормальному закону распреде
От: TailWind  
Дата: 17.12.20 18:55
Оценка:
Разве тут вторую компоненту через первую нельзя выразить?

W>>Слева вариант по формулам из википедии. А справа вариант, генерируемый функцией за авторством kov_serg.

W>>Правда ведь правый вариант выглядит немного не похожим на нормальное распределение?
_>Да косяк.
_>
_>function normal() 
_>    local a=math.sqrt(-2*math.log(math.random()))
_>    local b=2*math.pi*math.random()
_>    return a*math.cos(b), a*math.sin(b)
_>end
_>
Re[6]: Генерация случайных чисел по нормальному закону распреде
От: kov_serg Россия  
Дата: 17.12.20 19:05
Оценка:
Здравствуйте, TailWind, Вы писали:

TW>Разве тут вторую компоненту через первую нельзя выразить?

_>>
_>>function normal() 
_>>    local a=math.sqrt(-2*math.log(math.random()))
_>>    local b=2*math.pi*math.random()
_>>    return a*math.cos(b), a*math.sin(b)
_>>end
_>>

Нет
Re[7]: Генерация случайных чисел по нормальному закону распреде
От: TailWind  
Дата: 17.12.20 19:06
Оценка:
_>Нет

Да ладно?

cos(b) нельзя выразить через sin(b)?
Re[8]: Генерация случайных чисел по нормальному закону распр
От: watchmaker  
Дата: 17.12.20 19:23
Оценка:
Здравствуйте, TailWind, Вы писали:

_>>Нет


TW>Да ладно?


TW>cos(b) нельзя выразить через sin(b)?


Зная значение sin(b) можно хорошо предсказать возможные значения cos(b).
Но всё становится несколько интереснее, если вам известно лишь значение a * sin(b) и неизвестно значение a. Тогда предсказать возможные значения a * cos(b) становится не так просто.

Вообще это известный метод Box–Muller transform, и несмотря на кажущуюся похожесть выражений, зависимости между случайными величинами нет.
Отредактировано 17.12.2020 19:25 watchmaker . Предыдущая версия . Еще …
Отредактировано 17.12.2020 19:23 watchmaker . Предыдущая версия .
Re[9]: Генерация случайных чисел по нормальному закону распр
От: TailWind  
Дата: 17.12.20 19:32
Оценка:
Да
Я не прав

a * cos(b) = Q
a * sin(b) = Z

a = Q / cos(b)
a = Z / sin(b)

Q/cos(b) = Z / sin(b)

Q = Z * cos(b) / sin(b)

Спасибо, за интересную дискуссию
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.