Arrays.deepToString(arrayOfObject)
Выше функции печатает массив объектов разных примитивов.
[[AAAAA, BBBBB], [6, 12], [2003-04-01 00:00:00.0, 2003-10-01 00:00:00.0], [2003-09-30 00:00:00.0, 2004-03-31 00:00:00.0], [Interim, Interim], [2003-09-30, 2004-03-31]];
Преобразование Box-Muller - это то, что обычно используется. Это правильно создает значения с нормальным распределением.
http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_from_normal_distribution
http: //en.wikipedia.org/wiki/Box_Muller_transform
Математика проста. Вы генерируете два одинаковых числа, и из них вы получаете два нормально распределенных номера. Верните один, сохраните другой для следующего запроса случайного числа.
Компьютер является детерминированным устройством. В расчетах нет случайности. Кроме того, арифметическое устройство в ЦП может оценивать суммирование по некоторому конечному набору целых чисел (выполняя оценку в конечном поле) и конечный набор действительных рациональных чисел. А также выполняются побитовые операции. Math заключает сделку с более большими наборами, такими как [0.0, 1.0] с бесконечным числом точек.
Вы можете прослушивать какой-либо провод внутри компьютера с каким-то контроллером, но будут ли они иметь равномерные распределения? Я не знаю. Но если предположить, что это сигнал является результатом накопления значений огромного количества независимых случайных величин, тогда вы получите примерно нормальную распределенную случайную величину (это было доказано в теории вероятностей)
Существуют алгоритмы, называемые псевдореальными случайный генератор. Как я понял, целью псевдослучайного генератора является эмулирование случайности. И критерии доброты: - эмпирическое распределение сходится (в некотором смысле - точечно, равномерно, L2) к теоретическим - значения, которые вы получаете от случайного генератора, как представляется, идеальны. Конечно, это неправда с «реальной точки зрения», но мы предполагаем, что это правда.
Один из популярных методов - вы можете суммировать 12 irv с равномерными распределениями ... Но, честно говоря, при деривации Центральная предельная теорема с помо- щью преобразования Фурье, серия Тейлора, необходимо иметь n -> + inf предположения пару раз. Так, например, теоретико - Лично я не понимаю, как люди выполняют суммирование по 12 i.r.v. с равномерным распределением.
У меня была теория пробок в университете. И особенно для меня это просто математический вопрос. В университете я увидел следующую модель:
double generateUniform(double a, double b)
{
return uniformGen.generateReal(a, b);
}
double generateRelei(double sigma)
{
return sigma * sqrt(-2 * log(1.0 - uniformGen.generateReal(0.0, 1.0 -kEps)));
}
double generateNorm(double m, double sigma)
{
double y2 = generateUniform(0.0, 2 * kPi);
double y1 = generateRelei(1.0);
double x1 = y1 * cos(y2);
return sigma*x1 + m;
}
Такой способ, как сделать это, был просто примером, я предполагаю, что существуют другие способы его реализации.
Доказательство того, что это правильно, можно найти в этой книге «Москва, БМТУ, 2004: XVI Теория вероятностей, пример 6.12, с.246-247» из Крищенко Александр Петрович ISBN 5-7038-2485-0
К сожалению, я не знаю о существовании перевода этой книги на английский язык.
EDIT: С 12 августа 2011 года у нас есть C ++ 11 , который непосредственно предлагает std::normal_distribution
, что я и хотел сегодня.
Вот оригинальный ответ:
Вот некоторые решения, упорядоченные по возрастающей сложности.
https://web.archive.org/web/20151030215612/http://home.online. no / ~ pjacklam / notes / invnorm /
Надеюсь, что помогает
Peter
Список comp.lang.c FAQ разделяет три разных способа легко генерировать случайные числа с распределением Гаусса.
Вы можете взглянуть на это: http://c-faq.com/lib/gaussian.html
Вы можете использовать GSL . Некоторые полные примеры даны , чтобы продемонстрировать, как их использовать.
Если вы используете C ++ 11, вы можете использовать std::normal_distribution
:
#include <random>
std::default_random_engine generator;
std::normal_distribution<double> distribution(/*mean=*/0.0, /*stddev=*/1.0);
double randomNumber = distribution(generator);
Существует множество других распределений, которые вы можете использовать для преобразования вывода двигатель случайного числа.
Реализация Box-Muller:
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
using namespace std;
// return a uniformly distributed random number
double RandomGenerator()
{
return ( (double)(rand()) + 1. )/( (double)(RAND_MAX) + 1. );
}
// return a normally distributed random number
double normalRandom()
{
double y1=RandomGenerator();
double y2=RandomGenerator();
return cos(2*3.14*y2)*sqrt(-2.*log(y1));
}
int main(){
double sigma = 82.;
double Mi = 40.;
for(int i=0;i<100;i++){
double x = normalRandom()*sigma+Mi;
cout << " x = " << x << endl;
}
return 0;
}
Существуют различные алгоритмы для обратного кумулятивного нормального распределения. Самые популярные в количественном финансировании тестируются на http://chasethedevil.github.io/post/monte-carlo--inverse-cumulative-normal-distribution/
Кроме того, , он показывает недостаток Ziggurat, как подходы.
Используйте std::tr1::normal_distribution
.
Пространство имен std :: tr1 не является частью boost. Это пространство имен, которое содержит дополнения библиотеки из Технического отчета C ++ 1 и доступно в современных компиляторах Microsoft и gcc независимо от boost.
Я создал проект с открытым исходным кодом C ++ для стандартного теста генерации случайных чисел .
Он сравнивает несколько алгоритмов, включая
cpp11random
использует C ++ 11 std::normal_distribution
с std::minstd_rand
(это фактически преобразование Box-Muller в clang). Результаты версии с одной точностью (float
) на iMac Corei5-3330S@2.70GHz, clang 6.1, 64-bit:
[/g1]
Для правильности программа проверяет среднее, стандартное отклонение, асимметрию и эксцесс образцов. Было обнаружено, что метод CLT путем суммирования 4, 8 или 16 равномерных чисел не обладает хорошим куртозом, как другие методы.
Алгоритм Зиггурата имеет лучшую производительность, чем другие. Тем не менее, он не подходит для параллелизма SIMD, поскольку для этого нужен поиск в таблице и ветви. Box-Muller с набором инструкций SSE2 / AVX выполняется намного быстрее (x1.79, x2.99), чем версия алгоритма зиггурата, отличная от SIMD.
Поэтому я предлагаю использовать Box-Muller для архитектуры с SIMD наборы команд, и в противном случае может быть ziggurat.
PS в тесте используется простейший LCG PRNG для генерации однородных распределенных случайных чисел. Поэтому может быть недостаточно для некоторых приложений. Но сравнение производительности должно быть справедливым, потому что во всех реализациях используется тот же PRNG, поэтому в основном тест проверяет производительность преобразования.
Я выполнил определение PDF, данное в http://www.mathworks.com/help/stats/normal-distribution.html , и придумал следующее:
const double DBL_EPS_COMP = 1 - DBL_EPSILON; // DBL_EPSILON is defined in <limits.h>.
inline double RandU() {
return DBL_EPSILON + ((double) rand()/RAND_MAX);
}
inline double RandN2(double mu, double sigma) {
return mu + (rand()%2 ? -1.0 : 1.0)*sigma*pow(-log(DBL_EPS_COMP*RandU()), 0.5);
}
inline double RandN() {
return RandN2(0, 1.0);
}
Возможно, это не лучший подход, но это довольно просто.
Быстрый и простой метод состоит в том, чтобы просто суммировать количество равномерно распределенных случайных чисел и принимать их среднее значение. См. Центральную предельную теорему для полного объяснения, почему это работает.
Вот пример C ++, основанный на некоторых ссылках. Это быстро и грязно, вам лучше не изобретать и использовать библиотеку boost.
#include "math.h" // for RAND, and rand
double sampleNormal() {
double u = ((double) rand() / (RAND_MAX)) * 2 - 1;
double v = ((double) rand() / (RAND_MAX)) * 2 - 1;
double r = u * u + v * v;
if (r == 0 || r > 1) return sampleNormal();
double c = sqrt(-2 * log(r) / r);
return u * c;
}
Вы можете использовать график QQ для изучения результатов и посмотреть, насколько он приближается к реальному нормальному распределению (ранжируйте ваши образцы 1..x, превратите ряды в пропорции общего количества х, т. е. сколько образцов, получите значения z и запишите их. Прямая линия вверх - это желаемый результат).
Вот как вы создаете образцы на современном компиляторе C ++.
#include <random>
...
std::mt19937 generator;
double mean = 0.0;
double stddev = 1.0;
std::normal_distribution<double> normal(mean, stddev);
cerr << "Normal: " << normal(generator) << endl;
1) Графически интуитивно понятный способ генерации гауссовских случайных чисел заключается в использовании чего-то похожего на метод Монте-Карло. Вы создадите случайную точку в поле вокруг кривой Гаусса, используя ваш генератор псевдослучайных чисел в C. Вы можете вычислить, находится ли эта точка внутри или под распределением Гаусса, используя уравнение распределения. Если эта точка находится внутри гауссовского распределения, то вы получили свое гауссовское случайное число как значение x точки.
Этот метод не идеален, потому что технически гауссова кривая переходит к бесконечности, и вы не можете создать поле, которое приближается к бесконечности в измерении x. Но кривая Гуасса приближается к 0 в y-измерении довольно быстро, поэтому я бы не стал беспокоиться об этом. Ограничение размера ваших переменных в C может быть более ограничивающим фактором для вашей точности.
2) Другим способом было бы использовать Центральную предельную теорему, которая гласит, что при добавлении независимых случайных величин, они образуют нормальное распределение. Учитывая эту теорему, вы можете аппроксимировать гауссовское случайное число, добавив большое количество независимых случайных величин.
Эти методы не являются наиболее практичными, но это следует ожидать, если вы не хотите использовать существующую ранее библиотеку. Имейте в виду, что этот ответ исходит от кого-то, у кого мало или нет опыта исчисления или статистики.
Посмотрите: http://www.cplusplus.com/reference/random/normal_distribution/ . Это самый простой способ получения нормальных распределений.