Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Dark Byte
-17 / 46 / 12
Регистрация: 23.10.2014
Сообщений: 1,001
Завершенные тесты: 2
#1

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

05.11.2016, 11:21. Просмотров 650. Ответов 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
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Реализовать функцию (или класс) генерации случайных чисел, используя средства из заголовочника random (C++11) (C++):

Средства для генерации случайных чисел - C++
В Си было удобно подключить рандомные числа. через randomize(); a=random(10)-5; В Си++ кроме rand() есть способы еще подключить...

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

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

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

Генератор случайных чисел на С++ <random> - C++
генератор случайных чисел в &lt;random&gt; http://www.cplusplus.com/reference/random/ генератор постоянно генерирует одни и те же числа,...

Генератор случайных чисел random() - C++
Здраствуйте! Подскажите, пожалуйста, как сделать вывод случайных чисел в этой программе: #include &lt;iostream&gt; using namespace std;...

19
Nick Alte
Эксперт С++
1646 / 1018 / 120
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.11.2016, 11:33 #2
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от 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
-17 / 46 / 12
Регистрация: 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
2471 / 1140 / 241
Регистрация: 30.11.2013
Сообщений: 3,709
05.11.2016, 12:32 #4
Dark Byte, Генерация рандомных чисел
1
Nick Alte
Эксперт С++
1646 / 1018 / 120
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
05.11.2016, 12:57 #5
Цитата Сообщение от Dark Byte Посмотреть сообщение
Да нет я там возвращаю у себя QByteArray (Qt). Так что скастить не удастся.
Ну зачем же такой пессимизм. У QByteArray, как и у обычного vector, есть функции resize() и data(). Так что всё отлично кастится.
0
zarko97
279 / 39 / 0
Регистрация: 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-
Любитель чаепитий
3122 / 1462 / 351
Регистрация: 24.08.2014
Сообщений: 5,175
Записей в блоге: 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 / 0
Регистрация: 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
107 / 44 / 9
Регистрация: 17.10.2010
Сообщений: 685
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
6857 / 3058 / 524
Регистрация: 15.11.2014
Сообщений: 6,932
Завершенные тесты: 1
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-
Любитель чаепитий
3122 / 1462 / 351
Регистрация: 24.08.2014
Сообщений: 5,175
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 15:09 #11
Цитата Сообщение от isaak Посмотреть сообщение
все равно остались ошибки компиляции.
Для std::common_type_t и std::enable_if_t нужен с++14.
Как включить можно посмотреть здесь: Как включить в своей среде разработки поддержку определённого стандарта (С++11, С++14, С++17)
0
isaak
107 / 44 / 9
Регистрация: 17.10.2010
Сообщений: 685
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-
Любитель чаепитий
3122 / 1462 / 351
Регистрация: 24.08.2014
Сообщений: 5,175
Записей в блоге: 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
107 / 44 / 9
Регистрация: 17.10.2010
Сообщений: 685
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-
Любитель чаепитий
3122 / 1462 / 351
Регистрация: 24.08.2014
Сообщений: 5,175
Записей в блоге: 1
Завершенные тесты: 2
25.02.2017, 16:10 #15
Цитата Сообщение от isaak Посмотреть сообщение
Опять ошибки?
Вам видней.
Вы что, не можете одни и те же ошибки исправить? Гляньте документацию хотя бы, а не тупо лейте на форум свои вопросы...
http://en.cppreference.com/w/cpp/types/conditional
Так вы ничему не научитесь.
1
25.02.2017, 16:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.02.2017, 16:10
Привет! Вот еще темы с ответами:

Как указать диапазон генерации случайных чисел? - C++
Возник довольно глупый вопрос,как указать диапазон генерации случайных чисел в C++... int a=random(10); - тут генерируются числа от 1 до...

Формула для генерации случайных чисел заданного диапазона - C++
srand(time(NULL)); int massize = 3; int mas; for (int i = 0; i &lt; massize; i++) { for (int b = 0; b &lt; massize; b++) { ...

Ввод больших чисел используя массив или функцию С++ - C++
Помогите пожалуйста чайнику в С++ написать программку на С++, вводящую числа большой разрядности, используя массив)):help: (Классы для...

Подскажите функцию генерации случайных чисел - Visual Basic
Подскажите функцию генерации случайных чисел(не RND). Заранее СПАСИБО!


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

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

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