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 на каждой итерации цикла наводит на мысль, что автор, мягко говоря, не очень понимает для чего это всё нужно.

Пікірлер

Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
Кіріңіз немесе Тіркеліңіз
m
  • molni99
  • Қаз. 26, 2024, 1:37 Т.Ж.

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

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

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

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

C++ - Тест 003. Условия и циклы

  • Нәтиже:42ұпай,
  • Бағалау ұпайлары-8
Соңғы пікірлер
i
innorwallҚар. 8, 2024, 7:40 Т.Ж.
Qt/C++ - 039-сабақ. QSqlTableModel жүйесінде жолды бағандағы мән бойынша бояу әдісі priligy results This slowing of eGFR decline was observed in patients with and without low eGFR and in those with and without type 2 diabetes
i
innorwallҚар. 8, 2024, 2:45 Т.Ж.
QML - Урок 002. QML Android жүйесіндегі пайдаланушы түймесі 2007; 14 2 270 83 priligy dapoxetine 60mg Testicular imaging is sort of a unique niche right now, Гў
i
innorwallҚар. 8, 2024, 1:32 Т.Ж.
C++ - #pragma бір рет құрастыруды жылдамдатады ма? It could cause harm to the unborn baby buy generic priligy
i
innorwallҚар. 8, 2024, 12:50 Т.Ж.
ЖАМАНДЫҚ ЯРЕК. Google reCAPTCHA пайдалану buy priligy 60 urea in 50 patients treated by urea for mild hyponatremia developed it in the intensive care unit mean age 71 20 years
Енді форумда талқылаңыз
i
innorwallҚар. 8, 2024, 7:08 Т.Ж.
добавить qlineseries в функции School of Nursing, Long Island University, Brooklyn Campus, Brooklyn, NY, USA priligy dapoxetine 30mg
9
9AnonimҚаз. 25, 2024, 9:10 Т.Ж.
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…
F
FynjyШілде 22, 2024, 4:15 Т.Ж.
при создании qml проекта Kits есть но недоступны для выбора Поставил Qt Creator 11.0.2. Qt 6.4.3 При создании проекта Qml не могу выбрать Kits, они все недоступны, хотя настроены и при создании обычного Qt Widget приложения их можно выбрать. В чем может …

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