Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
Dark Byte
29 / 46 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
Завершенные тесты: 2
1

Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)

05.11.2016, 11:21. Просмотров 767. Ответов 19
Метки нет (Все метки)

Хотел написать небольшую обертку над stl-вским рандомом. Уж больно он сложный для использования. Застрял на такой простой вещи:
C++
1
2
3
4
5
6
7
8
9
10
11
12
class Random
{
public:
    int next(int min, int max)
    {
        std::uniform_int_distribution<int> uid(min, max);
        return uid(this->m_generator);
    }
    
private:
    std::mt19937 m_generator;
}
Там есть и инициализация и прочее, не буду приводить весь код не суть. Вопрос лишь в генерации чисел в диапазоне. Как я нагуглил для этого надо использовать uniform_int_distribution, но он требует указать диапазон в конструкторе, а это не комильфо. Ну т.е. при каждом вызове next будет новый объект создаваться. Зачем это надо? Можно как то это устаканить?

П.С. Т.е. было бы удобно создать его заранее как приватное поле класса, но он же не дает менять диапазон... Вот в чем проблема.

Добавлено через 5 минут
И еще вопрос по генерации массива байтов. Я пока не нашел решения изящнее чем просто генерировать рандомный int и из него битовыми операциями выковыривать байты. Может есть что то встроенное для этого?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.11.2016, 11:21
Ответы с готовыми решениями:

Средства для генерации случайных чисел
В Си было удобно подключить рандомные числа. через randomize();...

Реализовать алгоритм средних квадратов для генерации случайных чисел
Помогите написать программу: &quot;Реализовать алгоритм средних квадратов для...

Реализовать шаблонный класс или функцию
Опишите параметризованный класс односвязный список элементов (параметр – тип)....

Функция генерации случайных чисел
Здравствуйте, возник такой вопрос: мне нужно определить генерацию случайных...

Генератор случайных чисел random()
Здраствуйте! Подскажите, пожалуйста, как сделать вывод случайных чисел в этой...

19
Nick Alte
Эксперт С++
1648 / 1020 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.11.2016, 11:33 2
Лучший ответ Сообщение было отмечено Dark Byte как решение

Решение

Цитата Сообщение от Dark Byte Посмотреть сообщение
Ну т.е. при каждом вызове next будет новый объект создаваться. Зачем это надо? Можно как то это устаканить?
Это легковесный объект, и ничего страшного в этом нет. Можно смело пользоваться им как временным значением и не бояться издержек, после оптимизатора их не останется.

C++
1
2
3
4
int next(int minValue, int maxValue)
{
    return std::uniform_int_distribution<int>(min, max)(m_generator);
}
Цитата Сообщение от Dark Byte Посмотреть сообщение
Может есть что то встроенное для этого?
Где массив, там и указатели, а где указатели - там и static_cast, можно укладывать по одному int (лучше всё же unsigned) сразу в 4 байта. Особенно если размер массива кратен 4. Это не очень изящно, но весьма эффективно.
1
Dark Byte
29 / 46 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
Завершенные тесты: 2
05.11.2016, 11:36  [ТС] 3
Цитата Сообщение от Nick Alte Посмотреть сообщение
Где массив, там и указатели, а где указатели - там и static_cast, можно укладывать по одному int (лучше всё же unsigned) сразу в 4 байта. Особенно если размер массива кратен 4. Это не очень изящно, но весьма эффективно.
Да нет я там возвращаю у себя QByteArray (Qt). Так что скастить не удастся. Но думаю можно сделать прегенерируемый массив (генерировать с запасом как в стандартных контейнерах), в который будут записывать сгенерированные байты (генерировать кратно 4), а потом брать из него просто. Чтобы байты не терялись (это бы способствовало более быстрому вырождению генератора).
0
rikimaru2013
C++ Game Dev
2473 / 1141 / 349
Регистрация: 30.11.2013
Сообщений: 3,709
05.11.2016, 12:32 4
Dark Byte, Генерация рандомных чисел
1
Nick Alte
Эксперт С++
1648 / 1020 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.11.2016, 12:57 5
Цитата Сообщение от Dark Byte Посмотреть сообщение
Да нет я там возвращаю у себя QByteArray (Qt). Так что скастить не удастся.
Ну зачем же такой пессимизм. У QByteArray, как и у обычного vector, есть функции resize() и data(). Так что всё отлично кастится.
0
zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
25.02.2017, 12:15 6
Dark Byte, небольшая функция для рандомчика:
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
41
#include       <random>
#include        <array>
#include  <type_traits>
#include    <algorithm>
#include     <typeinfo>
#include   <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if_t<N, Dist&>
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
 
   template<class T1, class T2>
T random(T1&& min, T2&& max)
{
    using T = std::common_type_t<T1, T2>::type;
    
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
 
}
1
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 12:29 7
Цитата Сообщение от zarko97 Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
9
10
11
12
template<class T1, class T2>
T random(T1&& min, T2&& max)
{
* * using T = std::common_type_t<T1, T2>::type;
static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
using UniformInt = std::uniform_int_distribution<T>;
* * using UniformReal = std::uniform_real_distribution<T>;
* * using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
static auto& RandomEngine = randomEngine();
DistType uniformDistribution(min, max);
return uniformDistribution(RandomEngine);
}
Зря вы просто скопировали, теперь будут ошибки компиляции, ибо в возвращаемом значении стоит T, а определяется T только в теле функции.
Да и common_type_t указано с type, которое не нужно, ведь есть приставка _t.
Вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<class T1, class T2>
std::common_type_t<T1, T2> random(T1&& min, T2&& max)
{
    using T = std::common_type_t<T1, T2>;
    
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
Просто писал уже под ночь, да и не проверял, мозги уже не варили.
1
zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
25.02.2017, 12:32 8
GbaLog-, можно мини-макрос генернуть
C++
1
2
#define detectT \
    typename std::common_type_t<T1, T2>
0
isaak
112 / 49 / 19
Регистрация: 17.10.2010
Сообщений: 737
25.02.2017, 12:54 9
GbaLog-, все равно остались ошибки компиляции.
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
#include       <random>
#include        <array>
#include  <type_traits>
#include    <algorithm>
#include     <typeinfo>
#include   <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if_t<N, Dist&>
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
    template<class T1, class T2>
std::common_type_t<T1, T2> random(T1&& min, T2&& max)
{
    using T = std::common_type_t<T1, T2>;
 
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
}
Использую CodeBlock 16.01. C++11 стандарт подключен??????
0
Миниатюры
Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)  
hoggy
Заблокирован
Эксперт С++
25.02.2017, 14:23 10
Цитата Сообщение от isaak Посмотреть сообщение
Использую CodeBlock 16.01. C++11 стандарт подключен??????
std::enable_if_t просит с++14

в рамках с++11 это будет так:
C++
1
typename std::enable_if<N, Dist&>::type
0
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 15:09 11
Цитата Сообщение от isaak Посмотреть сообщение
все равно остались ошибки компиляции.
Для std::common_type_t и std::enable_if_t нужен с++14.
Как включить можно посмотреть здесь: Как включить в своей среде разработки поддержку определённого стандарта (С++11, С++14, С++17)
0
isaak
112 / 49 / 19
Регистрация: 17.10.2010
Сообщений: 737
25.02.2017, 15:11 12
hoggy, заменил как вы советуете:
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       <random>
#include        <array>
#include  <type_traits>
#include    <algorithm>
#include     <typeinfo>
#include   <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if<N, Dist&>::type
 
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
    template<class T1, class T2>
std::common_type_t<T1, T2> random(T1&& min, T2&& max)
{
    using T = std::common_type_t<T1, T2>;
 
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
}
Теперь вылезает одна ошибка в 24 строке???? Не знаю как ее исправить?????
0
Миниатюры
Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)  
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 15:21 13
Цитата Сообщение от isaak Посмотреть сообщение
Теперь вылезает одна ошибка в 24 строке
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typename std::common_type<T1, T2>::type random(T1&& min, T2&& max)
{
    using T = typename std::common_type<T1, T2>::type;
 
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
0
isaak
112 / 49 / 19
Регистрация: 17.10.2010
Сообщений: 737
25.02.2017, 15:48 14
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       <random>
#include        <array>
#include  <type_traits>
#include    <algorithm>
#include     <typeinfo>
#include   <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if<N, Dist&>::type
 
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
    template<class T1, class T2>
typename std::common_type<T1, T2>::type random(T1&& min, T2&& max)
{
    using T = typename std::common_type<T1, T2>::type;
 
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
}
Опять ошибки?????
0
Миниатюры
Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)  
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 16:10 15
Цитата Сообщение от isaak Посмотреть сообщение
Опять ошибки?
Вам видней.
Вы что, не можете одни и те же ошибки исправить? Гляньте документацию хотя бы, а не тупо лейте на форум свои вопросы...
http://en.cppreference.com/w/cpp/types/conditional
Так вы ничему не научитесь.
1
isaak
112 / 49 / 19
Регистрация: 17.10.2010
Сообщений: 737
25.02.2017, 16:25 16
Ошибки компилятор по мере исправления выдает каждый раз разные. Документацию я прочитал. Все равно не понятно.Тяжело даются стандарты C++11, C++14.
0
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 18:05 17
Цитата Сообщение от isaak Посмотреть сообщение
Ошибки компилятор по мере исправления выдает каждый раз разные.
Я не понимаю, вы меня обмануть пытаетесь что ли?
Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)

На всех 3-х ваших скриншотах одна и та же ошибка... Только названия отличаются.
Цитата Сообщение от isaak Посмотреть сообщение
Документацию я прочитал. Все равно не понятно.Тяжело даются стандарты C++11, C++14.
Стандарты тут не при чем, это полное непонимание работы шаблонов.
0
isaak
112 / 49 / 19
Регистрация: 17.10.2010
Сообщений: 737
26.02.2017, 14:02 18
Ошибки возникают при компиляции вашего кода. Значит у вас не понимания, что такое шаблоны. Если у вас ошибки в самом коде.
0
hoggy
Заблокирован
Эксперт С++
26.02.2017, 14:31 19
isaak,
Кончайте деццкий сад.
Берите в руки книжку
(Джоссатис, шаблоны),
Читам и проникаемся до полного просветления
Особенно внимание уделяем ключевому слову 'typename'
И что такое 'зависящее от параметра шаблона имя'

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

То, что вы не в состоянии собрать тривиальный код, не значит, что кто то не умеет шаблоны
Это значит, что конкретно вы их не умеете
0
GbaLog-
Любитель чаепитий
3167 / 1473 / 465
Регистрация: 24.08.2014
Сообщений: 5,210
Записей в блоге: 1
Завершенные тесты: 2
26.02.2017, 14:32 20

Цитата Сообщение от isaak Посмотреть сообщение
Ошибки возникают при компиляции вашего кода.
Вас не удивляет тот факт, что ошибки возникают только у вас?
Цитата Сообщение от isaak Посмотреть сообщение
Если у вас ошибки в самом коде.
Да ладно?!
Код из этого поста: Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11)
http://rextester.com/TUBXH88080
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
41
#include       <random>
#include        <array>
#include  <type_traits>
#include    <algorithm>
#include     <typeinfo>
#include   <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if_t<N, Dist&>
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
    template<class T1, class T2>
std::common_type_t<T1, T2> random(T1&& min, T2&& max)
{
    using T = std::common_type_t<T1, T2>;
 
    static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
    using UniformInt = std::uniform_int_distribution<T>;
    using UniformReal = std::uniform_real_distribution<T>;
    using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
    static auto& RandomEngine = randomEngine();
 
    DistType uniformDistribution(min, max);
 
    return uniformDistribution(RandomEngine);
}
}
 
int main() {}
0
26.02.2017, 14:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.02.2017, 14:32

Генератор случайных чисел на С++ <random>
генератор случайных чисел в &lt;random&gt;...

Пару вопрос по генерации случайных чисел.
Здраствуйте уважаемые мастера с++. 1). Мне надо в конструкторе...

Как указать диапазон генерации случайных чисел?
Возник довольно глупый вопрос,как указать диапазон генерации случайных чисел в...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru