Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/21: Рейтинг темы: голосов - 21, средняя оценка - 4.62
7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175

Какой алгоритм рандомизации для чисел с плавающей запятой выбрать?

14.01.2020, 15:13. Показов 4394. Ответов 24
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго!
При попытке генерации двух чисел, методом вихря Мерсенна, происходит неудовлетворительная генерация.
Ставлю диапазон:
C++
1
RandomBetweenDouble(0.0, numeric_limits<double>::max()))
И код:
C++
1
2
3
4
5
6
7
8
double RandomBetweenDouble(double a, double b)
{
    random_device rd;                   //Недетерминированный генератор
    mt19937 gen(rd());                  //Генерация методом вихря Мерсенна
    uniform_real_distribution<> dist(a, b); //Задание границ генерации числа a <= с <= b
    double c = dist(gen);                   //Генерация
    return c;
}
Очень плохо генерирует, про очень плохо, я имею ввиду, что числа, ну в районе Х.ХХе+30Х.
То есть да, случайные числа каждый раз выбрасываются. Но хотелось бы разброс побольше по типу: Х.ХХе+301, Х.ХХе+56, Х.ХХе+81, Х.ХХе+271 итд...
Есть план как это сделать(но он мне очень не нравится): Генерировать вихрем числа от 0.0 до 9.99, переводить это в строку, прикреплять к строке 'e+', генерировать второе число от 0 до 308 int-вым генератором, переводить этот int в строку и присоединять к уже существующей строке, а, затем, уже переводить строку в double.

Но все-таки хочется хороший генератор, потому что он для криптографического алгоритма.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
14.01.2020, 15:13
Ответы с готовыми решениями:

Программа для умножения чисел с плавающей запятой
Помогите пожалуйста составить программу:cry: Составить программу на ассемблере, для реализации умножения чисел с плавающей запятой ...

Составить программу для вычитания чисел с плавающей запятой
Нужно составить программу, которая переводила бы два вводимых десятичных числа с плавающей запятой в двоичные, вычитала одно число из...

Нормализация чисел с плавающей запятой
Здравствуйте. Пишу макросы для автоматической проверки лабораторных работ. Столкнулась с проблемой: не могу реализовать перевод чисел в...

24
7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175
14.01.2020, 21:20  [ТС]
Студворк — интернет-сервис помощи студентам
Я пока подумал, числа с плавающей запятой откладываются до лучших времён, будет написана специальная библиотека, которая позволит грамотно обрабатывать R-числа. Пока ограничимся uint64, этого хватит за глаза для гарантии уникальности.
Хочется с помощью функции, передавая два числа, min и max. В нашем случае uint64.
C++
1
2
3
4
5
6
template <typename T>
T RandomBetween(T a, T b)
{
    //Генерация числа с: a<=c<=b
    return c;
}
Равновероятно генерировать любое число из диапазона [а,b].
0
653 / 466 / 183
Регистрация: 23.04.2019
Сообщений: 1,987
14.01.2020, 21:34
Цитата Сообщение от Battary Посмотреть сообщение
Хочется с помощью функции, передавая два числа, min и max.
C++
1
2
3
4
5
6
7
8
9
#include <random>
 
template <typename T>
T RandomBetween(T a, T b)
{
 
    //Генерация числа с: a<=c<=b
    return a + rand() % (b - a + 1);
}
Та на изи

Добавлено через 1 минуту
Цитата Сообщение от Battary Посмотреть сообщение
Равновероятно
нууу) хоть это и псевдорандом, равновероятность не гарантируется
0
694 / 304 / 99
Регистрация: 04.07.2014
Сообщений: 851
15.01.2020, 01:13
Лучший ответ Сообщение было отмечено Battary как решение

Решение

Цитата Сообщение от Battary Посмотреть сообщение
Равновероятно генерировать любое число из диапазона [а,b].
uniform_int_distribution

Цитата Сообщение от AndryS1 Посмотреть сообщение
return a + rand() % (b - a + 1);
ТС просит генератор для криптографии, а не Г на палочке.
Линейный конгруэнтный метод: Возможность использования в криптографии

Хотя линейный конгруэнтный метод порождает статистически хорошую псевдослучайную последовательность чисел, он не является криптографически стойким. Генераторы на основе линейного конгруэнтного метода являются предсказуемыми, поэтому их нельзя использовать в криптографии. Впервые генераторы на основе линейного конгруэнтного метода были взломаны Джимом Ридсом (Jim Reeds), а затем Джоан Бояр (Joan Boyar). Ей удалось также вскрыть квадратические и кубические генераторы. Другие исследователи расширили идеи Бояр, разработав способы вскрытия любого полиномиального генератора. Таким образом, была доказана бесполезность генераторов на основе конгруэнтных методов для криптографии. Однако генераторы на основе линейного конгруэнтного метода сохраняют свою полезность для некриптографических приложений, например, для моделирования. Они эффективны и в большинстве используемых эмпирических тестах демонстрируют хорошие статистические характеристики
Смотри также RANDU

З.Ы. Вихрь Мерсенна тоже не подходит для криптографии, в C++ ближе всего random_device

З.З.Ы. boost/multiprecision/cpp_int.hpp

Добавлено через 55 минут
Для больших чисел почти можно как-то так

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <random>
#include <stdexcept>
 
#include <boost/multiprecision/cpp_int.hpp>
 
using BigInt = boost::multiprecision::cpp_int;
 
BigInt RandomBetween(const BigInt &a, const BigInt &b) {
  std::random_device rd;
 
  uint32_t rd_max = 0xFFFFFFFFu;
  std::uniform_int_distribution<uint32_t> dist(0, rd_max - 1);
 
  BigInt result = 0;
  BigInt c = b - a;
  BigInt d = c * c * c;
 
  while (result < d) {
    result = (result * rd_max) + dist(rd);
  }
 
  result = a + (result % (c + 1));
  return result;
}
 
int main() {
 
  BigInt a{"12345678901234567890123456789012345678901234567890"};
  BigInt b{"99999999999999999999999999999999999999999999999999"};
 
  std::cout << a << std::endl;
  std::cout << b << std::endl;
 
  for (size_t i = 0; i < 20; ++i) {
    std::cout << RandomBetween(a, b) << std::endl;
  }
 
  return 0;
}
Результат
Кликните здесь для просмотра всего текста

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
12345678901234567890123456789012345678901234567890
99999999999999999999999999999999999999999999999999
84434353727817566854949735814101712753062869604816
54852365388108865265514780459831703010383177442774
72722938349669976451898332183523506042007830491414
91701786944064583328625920315131710851831395632563
12891860005374834651976030877153482338361227689416
19391497652302776767276523429483071969929663966749
31246510290710766426537006219961851885631499915112
63142739638384489064140336166034007458469940062915
48019651036249997478795703095539813556873136842845
55097305539494510906019519989780527549675004370758
65872431759959004135933414723046069215759906650028
17461984238493008942936299161587701829099877694877
85103608523904147316296222278348258126263035087968
16234743770117210110865956655546075772230390212124
71979409307681339212122567410913992168907008630702
54548072970661918580115473087487287094664756920051
77575413025963635680239377791432582969291742532156
14170247491759561357916834130360490131442082731127
16140493409717158365950647160684892141084965091810
52122445009448586289329443397338384935987818604741


Если a=0 и b=k^n, где k <= MAX_INT, то можно уйти от остатков
1
7 / 6 / 1
Регистрация: 29.10.2016
Сообщений: 175
15.01.2020, 09:18  [ТС]
Сделал 2 варианта:
В этом варианте необходимо будет провести моделирование, чтобы узнать, действительно ли распределение равномерное по всей оси положительных чисел.
C++
1
2
3
4
5
6
7
uint64_t RandomBetweenuint64_t(uint64_t a, uint64_t b)
{
    random_device rd;                       //Недетерминированный генератор
    uniform_int_distribution<uint64_t> dist(a, b);  //Задание границ генерации числа a <= с <= b
    uint64_t c = dist(rd);                          //Генерация
    return c;
}
А этот да, генерирует случайное число на интервале, за счет использования 32бит можно использовать соответствующие генераторы. Его большой минус - чем больше разница между min и max, тем дольше он вычисляет.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
uint64_t RandomBetweenuint64_tByMult(uint64_t a, uint64_t b) 
{
    uint32_t coef = 1;
 
    if ((b - a) > numeric_limits<unsigned long>::max()) 
    { 
        coef = (b - a) / numeric_limits<unsigned long>::max();
    }
 
    random_device rd;
    uniform_int_distribution<uint32_t> dist1(numeric_limits<unsigned long>::min(), numeric_limits<unsigned long>::max());
    uniform_int_distribution<uint32_t> dist2(1, coef);
 
    uint32_t randomBetween = 0;
 
    coef = dist2(rd);
 
    for (size_t i = 0; i < coef; i++)
    {
        randomBetween += dist1(rd);
    }
 
    uint64_t c = a + randomBetween;
    return c;
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
15.01.2020, 09:29
Цитата Сообщение от Croessmah Посмотреть сообщение
Зачем real для генерации целого?
Низачем, обычный копипаст
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.01.2020, 09:29

Округление чисел с плавающей запятой
Здравствуйте товарищи программисты. Есть вопрос по функции FloatToStrF. Для моей задачи нужно записывать в текстовый файл числа с точностью...

Сравнение чисел с плавающей запятой
Сравнение чисел с плавающей запятой. В этой теме я попробую &quot;просто&quot; объяснить новичкам в программировании что есть тип double...

Вычисления с чисел с плавающей запятой
Есть в БД поле с числом (например 0,12). Формат в БД: Одинарное с плавающей точкой, Основной, 2 цифры после запятой. Нужно умножить...

Произведение чисел с плавающей запятой
Требуется реализовать произведение чисел с плавающей запятой, длинных чисел, к примеру 1234567890.9 и 1234567890.9, так что бы их результат...

Умножение чисел с плавающей запятой
Тут произошёл интересный случай, когда сделал умножение я увидел что любое число например это будет 3 ,может множется на любое кроме тех, у...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
25
Ответ Создать тему
Новые блоги и статьи
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы Всем привет! Хочу поделиться свежим (и довольно. . .
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения: - добавлена многоязычность - добавлено снятие скриншотов - добавлено поддержание бафов хождения по воде (для жреца, дк и шамана) - и так, по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru