Evgenii Legotckoi
Evgenii LegotckoiЖел. 14, 2017, 5:10 Т.Қ.

Qt/C++ - 074-сабақ. Кездейсоқ STD кітапханасын пайдаланып жалған кездейсоқ сандарды құру

Кездейсоқ сандарды генерациялау, мысалы, компьютерлік ойында қарудың зақымдалуын есептеу немесе кездейсоқ сандар графигін көрсету үшін қажет болуы мүмкін.

Qt кездейсоқ сандарды генерациялау үшін qrand функциясын қамтамасыз етеді және Qt 5.10 бастап QRandomGenerator класы.

Qt-де кездейсоқ мәндерді қалай алуға болатынын және олардың қаншалықты кездейсоқ екенін көрейік.


үлкен

Біз бастап және дейін мәндер ауқымында сандарды жасаймыз. Ол үшін екі функция жазамыз.

static int randomBetween(int low, int high)
{
    return (qrand() % ((high + 1) - low) + low);
}

static int randomBetween(int low, int high, int seed)
{
    qsrand(seed); // Setting a base number for counting a random in qrand
    return (qrand() % ((high + 1) - low) + low);
}

Бірінші функция ең кіші саннан ең үлкеніне дейін кездейсоқ мәнді жасайды. Ал екіншісінде, qsrand функциясын пайдалана отырып, базалық сан орнатылады, ол сан жасалатын Qt жалған кездейсоқ сандар генераторы үшін негіз болады. Бұл негізгі сан жүйе уақыты миллисекундтар болуы мүмкін.

Осы функцияларды қолданайық.

#include <QCoreApplication>
#include <QDateTime>
#include <iostream>

static int randomBetween(int low, int high)
{
    return (qrand() % ((high + 1) - low) + low);
}

static int randomBetween(int low, int high, int seed)
{
    qsrand(seed); // Setting the base number for counting a random host in qrand
    return (qrand() % ((high + 1) - low) + low);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << "Random Qt 1 - ";
    for (int i = 0; i < 15; ++i)
    {
        std::cout << randomBetween(15, 43) << " ";
    }
    std::cout << std::endl;

    std::cout << "Random Qt 2 - ";
    for (int i = 0; i < 15; ++i)
    {
        std::cout << randomBetween(15, 43, QDateTime::currentMSecsSinceEpoch()) << " ";
    }
    std::cout << std::endl;

    return a.exec();
}

Біз келесі нәтижені аламыз.

Random Qt 1 - 15 21 31 27 17 34 43 33 22 32 30 34 35 38 31 
Random Qt 2 - 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 

Енді алынған нәтижені талдап көрейік.

Бірінші жағдайда сандар кездейсоқ болып шықты... Ал қанша? Бағдарламаны қатарынан бірнеше рет іске қосуға тырыссаңыз, сандар әр уақытта бірдей болатынын көресіз, бұл өте жақсы емес және өте кездейсоқ емес.

Екінші нұсқаға келетін болсақ, мұнда барлық сандар бірдей болып шықты. Мәселе мынада, біз әр уақытта негізгі нөмірді бірдей сан етіп орнатуға тырыстық. Ақыр соңында, екі ГГц жиілігі бар процессор бұл қарапайым циклды өте жылдам орындайды, яғни миллисекундтардағы уақыт өзгеруге уақыт болмайды, яғни базалық нөмір бірдей болады. Ал негізгі нөмірді орнатқан кезде генерация ең басынан орындалады, бұл жағдайда оның өте кездейсоқ емес екенін көресіз.

Енді Qt [5.10] ішінде бізге не ұсынылғанын көрейік (https://evileg.com/post/312/)

QRandomGenerator

QRandomGenerator қолданбасы келесідей болады

#include <QCoreApplication>
#include <iostream>

#include <QRandomGenerator>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << "Random Qt 3 - ";
    QRandomGenerator generator;
    for (int i = 0; i < 15; ++i)
    {
        qint64 value = generator.generate() & std::numeric_limits<qint64>::max();
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return a.exec();
}

Шығару келесідей болады

Random Qt 3 - 853323747 2396352728 3025954838 2985633182 2815751046 340588426 3587208406 298087538 2912478009 3642122814 3202916223 799257577 1872145992 639469699 3201121432

Шындығында, qrand-пен бірдей мәселе осы жерде қайталанады, бағдарламаны қайта іске қосқанда, сандар қайталанатынын көресіз. Qt 5.10 шығарылымының жаңалықтары бұл сынып қалыпты qrand-қа қарағанда жақсы жұмыс істейтінін айтады, бірақ іс жүзінде мәселе сол күйінде қалады. Мүмкін, кездейсоқ сандарды генерациялауды үнемі қолданатын бағдарламаның ішінде ұзағырақ тестілеу кезінде сіз айтарлықтай айырмашылықтарды көре аласыз, бірақ мұндай қарапайым нұсқаның өзінде кемшіліктер бар.

Не істеу?

Бір жоба үшін кездейсоқ сандарды генерациялаудың қолайлы шешімін табуға тырысып, мен кездейсоқ сандарды генерациялаудың қолайлы нұсқасы бар C ++ 11 стандарты үшін STD кітапханасында кездейсоқ кітапхана бар екендігі туралы ақпаратты таба алдым. Git Hub сайтында өте қызықты бір кітапхананың іске асырылуы табылды. Осы кітапхананы негізге ала отырып, мен ұрпаққа шағын сынып жаздым (жолдардың арасын оқыңыз, өзім түсіну үшін аздап қайта жаздым).

Random.hpp

Мұнда енгізілген класс белгілі бір ауқымда кездейсоқ мәндерді алу үшін статикалық әдістерді орындау үшін Myers синглтонын пайдаланады. Кездейсоқ сандар генераторларының барлығын инициализациялаудан гөрі бір статикалық класс әдісін дұрыс жерде шақыру әлдеқайда оңай. Сыныптың өзі бүтін сан түрлерімен де, өзгермелі нүкте түрлерімен де жұмыс істейді.

#ifndef RANDOM_HPP
#define RANDOM_HPP

#include <random>

namespace details
{
    /// True if type T is applicable by a std::uniform_int_distribution
    template<class T>
    struct is_uniform_int {
        static constexpr bool value =
                std::is_same<T,              short>::value ||
                std::is_same<T,                int>::value ||
                std::is_same<T,               long>::value ||
                std::is_same<T,          long long>::value ||
                std::is_same<T,     unsigned short>::value ||
                std::is_same<T,       unsigned int>::value ||
                std::is_same<T,      unsigned long>::value ||
                std::is_same<T, unsigned long long>::value;
    };

    /// True if type T is applicable by a std::uniform_real_distribution
    template<class T>
    struct is_uniform_real {
        static constexpr bool value =
                std::is_same<T,       float>::value ||
                std::is_same<T,      double>::value ||
                std::is_same<T, long double>::value;
    };
}

class Random
{
    template <class T> using IntDist = std::uniform_int_distribution<T>;
    template <class T> using RealDist = std::uniform_real_distribution<T>;

public:
    template <class T>
    static typename std::enable_if<details::is_uniform_int<T>::value, T>::type get(T from = std::numeric_limits<T>::min(), T to = std::numeric_limits<T>::max())
    {
        if (from > to) std::swap(from, to);
        IntDist<T> dist{from, to};
        return dist(instance().engine());
    }

    template <class T>
    static typename std::enable_if<details::is_uniform_real<T>::value, T>::type get(T from = std::numeric_limits<T>::min(), T to = std::numeric_limits<T>::max())
    {
        if (from > to) std::swap(from, to);
        RealDist<T> dist{from, to};
        return dist(instance().engine());
    }

    std::mt19937& engine() { return m_mt; }

protected:
    static Random& instance()
    {
        static Random inst;
        return inst;
    }

private:
    std::random_device m_rd; // Random Number Generator
    std::mt19937 m_mt;       // Standard random number generator

    Random() : m_mt(m_rd()) {}
    ~Random() {}
    Random(const Random&) = delete;
    Random& operator = (const Random&) = delete;
};

#endif // RANDOM_HPP

main.cpp

Ал енді қолданба

#include <QCoreApplication>

#include "Random.hpp"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    std::cout << "Random STD  - ";
    for (int i = 0; i < 15; ++i)
    {
        std::cout << Random::get(15, 43) << " ";
    }
    std::cout << std::endl;
    return a.exec();
}

Қорытынды

Random STD  - 38 29 36 38 21 32 33 39 31 15 33 16 36 38 35 

Бұл жағдайда біз сандардың кездейсоқ шығарылымын аламыз және бағдарлама іске қосылған сайын сандар қайталанбайды. Кездейсоқтыққа келетін болсақ, мен ойында деңгейді құру үшін осы Random класын пайдаланған кезде бұған жеке көзім жетті. Әр жолы ойындағы заттардың орналасуы қайталанбады. Бұған qrand арқылы жету өте қиын болды.

Сонымен, C++11 псевдокездейсоқ сандарды жеткілікті жоғары сапалы генерациялауға мүмкіндік береді.

Міне, мен бұл мәселені зерттеген GitHub кітапханасынан сілтеме .

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

Дмитрий
  • Қаз. 29, 2020, 9:37 Т.Ж.
  • (өңделген)

А использование функции global() не решает ли эти проблемы?

value = QRandomGenerator::global()->bounded(15, 43);

Получаемая последовательность каждый раз новая.

r
  • Қаң. 17, 2021, 4:09 Т.Ж.

Дмитрий, решает. Просто автор, видимо, не сильно озаботился изучением документации QRandomGenerator.
Да и в листинге с использованием qrand вызов функции qsrand на каждой итерации цикла наводит на мысль, что автор, мягко говоря, не очень понимает для чего это всё нужно.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
OI
  • Ora Iro
  • Жел. 24, 2024, 6:38 Т.Ж.

C++ - Тест 001. Первая программа и типы данных

  • Нәтиже:40ұпай,
  • Бағалау ұпайлары-8
AD

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:50ұпай,
  • Бағалау ұпайлары-4
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

C++ - Тест 004. Указатели, Массивы и Циклы

  • Нәтиже:80ұпай,
  • Бағалау ұпайлары4
Соңғы пікірлер
ИМ
Игорь МаксимовҚар. 22, 2024, 11:51 Т.Ж.
Django - Оқулық 017. Теңшелген Django кіру беті Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiҚаз. 31, 2024, 2:37 Т.Қ.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEҚаз. 19, 2024, 8:19 Т.Ж.
Qt Creator көмегімен fb3 файл оқу құралы Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовҚаз. 5, 2024, 7:51 Т.Ж.
Django - Сабақ 064. Python Markdown кеңейтімін қалай жазуға болады Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5Шілде 5, 2024, 11:02 Т.Ж.
QML - Сабақ 016. SQLite деректер қоры және онымен QML Qt-та жұмыс істеу Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Енді форумда талқылаңыз
Evgenii Legotckoi
Evgenii LegotckoiМаусым 24, 2024, 3:11 Т.Қ.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Қар. 15, 2024, 6:04 Т.Ж.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectМаусым 4, 2022, 3:49 Т.Ж.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

Бізді әлеуметтік желілерде бақылаңыз