Итак, я видел доклад под названием rand() Считается вредным, и в нем пропагандировалось использование парадигмы механизма распределения генерации случайных чисел вместо простой парадигмы std::rand() плюс модуль.
Однако мне хотелось воочию увидеть недостатки std::rand(), поэтому я провел быстрый эксперимент:
< ol>
[*]По сути, я написал две функции getRandNum_Old() и getRandNum_New(), которые генерировали случайное число от 0 до 5 включительно, используя std::rand() и std::mt19937+std::uniform_int_distribution соответственно.
[*]Затем я сгенерировал 960 000 (делящихся на 6) случайных чисел, используя «старый» способ, и записал частоты чисел 0-5. Затем я рассчитал стандартное отклонение этих частот. Я ищу как можно меньшее стандартное отклонение, поскольку именно это и произошло бы, если бы распределение было действительно равномерным.
[*]Я запустил это моделирование 1000 раз и записал стандартное отклонение для каждая симуляция. Я также записал время, которое это заняло, в миллисекундах.
[*]После этого я сделал то же самое еще раз, но на этот раз сгенерировал случайные числа «новым» способом.
< li>Наконец, я рассчитал среднее и стандартное отклонение списка стандартных отклонений как для старого, так и для нового способа, а также среднее и стандартное отклонение для списка времен, взятых как для старого, так и для нового способа.
Вот какие результаты:
[OLD WAY]
Spread
mean: 346.554406
std dev: 110.318361
Time Taken (ms)
mean: 6.662910
std dev: 0.366301
[NEW WAY]
Spread
mean: 350.346792
std dev: 110.449190
Time Taken (ms)
mean: 28.053907
std dev: 0.654964
Удивительно, но совокупный разброс рулонов был одинаковым для обоих методов. То есть std::mt19937+std::uniform_int_distribution не был «более единообразным», чем простой std::rand()+%. Еще одно наблюдение, которое я сделал, заключалось в том, что новый метод работал примерно в 4 раза медленнее, чем старый. В целом казалось, что я заплатил огромную цену за скорость, почти не получив прироста в качестве.
Может быть мой эксперимент каким-то образом ошибочен? Или std::rand() действительно не так уж и плох, а может быть, даже лучше?
Для справки, вот код, который я использовал полностью:
#include
#include
#include
#include
int getRandNum_Old() {
static bool init = false;
if (!init) {
std::srand(time(nullptr)); // Seed std::rand
init = true;
}
return std::rand() % 6;
}
int getRandNum_New() {
static bool init = false;
static std::random_device rd;
static std::mt19937 eng;
static std::uniform_int_distribution dist(0,5);
if (!init) {
eng.seed(rd()); // Seed random engine
init = true;
}
return dist(eng);
}
template
double mean(T* data, int n) {
double m = 0;
std::for_each(data, data+n, [&](T x){ m += x; });
m /= n;
return m;
}
template
double stdDev(T* data, int n) {
double m = mean(data, n);
double sd = 0.0;
std::for_each(data, data+n, [&](T x){ sd += ((x-m) * (x-m)); });
sd /= n;
sd = sqrt(sd);
return sd;
}
int main() {
const int N = 960000; // Number of trials
const int M = 1000; // Number of simulations
const int D = 6; // Num sides on die
/* Do the things the "old" way (blech) */
int freqList_Old[D];
double stdDevList_Old[M];
double timeTakenList_Old[M];
for (int j = 0; j < M; j++) {
auto start = std::chrono::high_resolution_clock::now();
std::fill_n(freqList_Old, D, 0);
for (int i = 0; i < N; i++) {
int roll = getRandNum_Old();
freqList_Old[roll] += 1;
}
stdDevList_Old[j] = stdDev(freqList_Old, D);
auto end = std::chrono::high_resolution_clock::now();
auto dur = std::chrono::duration_cast(end-start);
double timeTaken = dur.count() / 1000.0;
timeTakenList_Old[j] = timeTaken;
}
/* Do the things the cool new way! */
int freqList_New[D];
double stdDevList_New[M];
double timeTakenList_New[M];
for (int j = 0; j < M; j++) {
auto start = std::chrono::high_resolution_clock::now();
std::fill_n(freqList_New, D, 0);
for (int i = 0; i < N; i++) {
int roll = getRandNum_New();
freqList_New[roll] += 1;
}
stdDevList_New[j] = stdDev(freqList_New, D);
auto end = std::chrono::high_resolution_clock::now();
auto dur = std::chrono::duration_cast(end-start);
double timeTaken = dur.count() / 1000.0;
timeTakenList_New[j] = timeTaken;
}
/* Display Results */
printf("[OLD WAY]\n");
printf("Spread\n");
printf(" mean: %.6f\n", mean(stdDevList_Old, M));
printf(" std dev: %.6f\n", stdDev(stdDevList_Old, M));
printf("Time Taken (ms)\n");
printf(" mean: %.6f\n", mean(timeTakenList_Old, M));
printf(" std dev: %.6f\n", stdDev(timeTakenList_Old, M));
printf("\n");
printf("[NEW WAY]\n");
printf("Spread\n");
printf(" mean: %.6f\n", mean(stdDevList_New, M));
printf(" std dev: %.6f\n", stdDev(stdDevList_New, M));
printf("Time Taken (ms)\n");
printf(" mean: %.6f\n", mean(timeTakenList_New, M));
printf(" std dev: %.6f\n", stdDev(timeTakenList_New, M));
}
Подробнее здесь: https://stackoverflow.com/questions/530 ... an-stdrand
Почему новая библиотека случайных чисел лучше, чем std::rand()? ⇐ C++
Программы на C++. Форум разработчиков
-
Anonymous
1714138805
Anonymous
Итак, я видел доклад под названием rand() Считается вредным, и в нем пропагандировалось использование парадигмы механизма распределения генерации случайных чисел вместо простой парадигмы std::rand() плюс модуль.
Однако мне хотелось воочию увидеть недостатки std::rand(), поэтому я провел быстрый эксперимент:
< ol>
[*]По сути, я написал две функции getRandNum_Old() и getRandNum_New(), которые генерировали случайное число от 0 до 5 включительно, используя std::rand() и std::mt19937+std::uniform_int_distribution соответственно.
[*]Затем я сгенерировал 960 000 (делящихся на 6) случайных чисел, используя «старый» способ, и записал частоты чисел 0-5. Затем я рассчитал стандартное отклонение этих частот. Я ищу как можно меньшее стандартное отклонение, поскольку именно это и произошло бы, если бы распределение было действительно равномерным.
[*]Я запустил это моделирование 1000 раз и записал стандартное отклонение для каждая симуляция. Я также записал время, которое это заняло, в миллисекундах.
[*]После этого я сделал то же самое еще раз, но на этот раз сгенерировал случайные числа «новым» способом.
< li>Наконец, я рассчитал среднее и стандартное отклонение списка стандартных отклонений как для старого, так и для нового способа, а также среднее и стандартное отклонение для списка времен, взятых как для старого, так и для нового способа.
Вот какие результаты:
[OLD WAY]
Spread
mean: 346.554406
std dev: 110.318361
Time Taken (ms)
mean: 6.662910
std dev: 0.366301
[NEW WAY]
Spread
mean: 350.346792
std dev: 110.449190
Time Taken (ms)
mean: 28.053907
std dev: 0.654964
Удивительно, но совокупный разброс рулонов был одинаковым для обоих методов. То есть std::mt19937+std::uniform_int_distribution не был «более единообразным», чем простой std::rand()+%. Еще одно наблюдение, которое я сделал, заключалось в том, что новый метод работал примерно в 4 раза медленнее, чем старый. В целом казалось, что я заплатил огромную цену за скорость, почти не получив прироста в качестве.
Может быть мой эксперимент каким-то образом ошибочен? Или std::rand() действительно не так уж и плох, а может быть, даже лучше?
Для справки, вот код, который я использовал полностью:
#include
#include
#include
#include
int getRandNum_Old() {
static bool init = false;
if (!init) {
std::srand(time(nullptr)); // Seed std::rand
init = true;
}
return std::rand() % 6;
}
int getRandNum_New() {
static bool init = false;
static std::random_device rd;
static std::mt19937 eng;
static std::uniform_int_distribution dist(0,5);
if (!init) {
eng.seed(rd()); // Seed random engine
init = true;
}
return dist(eng);
}
template
double mean(T* data, int n) {
double m = 0;
std::for_each(data, data+n, [&](T x){ m += x; });
m /= n;
return m;
}
template
double stdDev(T* data, int n) {
double m = mean(data, n);
double sd = 0.0;
std::for_each(data, data+n, [&](T x){ sd += ((x-m) * (x-m)); });
sd /= n;
sd = sqrt(sd);
return sd;
}
int main() {
const int N = 960000; // Number of trials
const int M = 1000; // Number of simulations
const int D = 6; // Num sides on die
/* Do the things the "old" way (blech) */
int freqList_Old[D];
double stdDevList_Old[M];
double timeTakenList_Old[M];
for (int j = 0; j < M; j++) {
auto start = std::chrono::high_resolution_clock::now();
std::fill_n(freqList_Old, D, 0);
for (int i = 0; i < N; i++) {
int roll = getRandNum_Old();
freqList_Old[roll] += 1;
}
stdDevList_Old[j] = stdDev(freqList_Old, D);
auto end = std::chrono::high_resolution_clock::now();
auto dur = std::chrono::duration_cast(end-start);
double timeTaken = dur.count() / 1000.0;
timeTakenList_Old[j] = timeTaken;
}
/* Do the things the cool new way! */
int freqList_New[D];
double stdDevList_New[M];
double timeTakenList_New[M];
for (int j = 0; j < M; j++) {
auto start = std::chrono::high_resolution_clock::now();
std::fill_n(freqList_New, D, 0);
for (int i = 0; i < N; i++) {
int roll = getRandNum_New();
freqList_New[roll] += 1;
}
stdDevList_New[j] = stdDev(freqList_New, D);
auto end = std::chrono::high_resolution_clock::now();
auto dur = std::chrono::duration_cast(end-start);
double timeTaken = dur.count() / 1000.0;
timeTakenList_New[j] = timeTaken;
}
/* Display Results */
printf("[OLD WAY]\n");
printf("Spread\n");
printf(" mean: %.6f\n", mean(stdDevList_Old, M));
printf(" std dev: %.6f\n", stdDev(stdDevList_Old, M));
printf("Time Taken (ms)\n");
printf(" mean: %.6f\n", mean(timeTakenList_Old, M));
printf(" std dev: %.6f\n", stdDev(timeTakenList_Old, M));
printf("\n");
printf("[NEW WAY]\n");
printf("Spread\n");
printf(" mean: %.6f\n", mean(stdDevList_New, M));
printf(" std dev: %.6f\n", stdDev(stdDevList_New, M));
printf("Time Taken (ms)\n");
printf(" mean: %.6f\n", mean(timeTakenList_New, M));
printf(" std dev: %.6f\n", stdDev(timeTakenList_New, M));
}
Подробнее здесь: [url]https://stackoverflow.com/questions/53040940/why-is-the-new-random-library-better-than-stdrand[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия