Хроно с разными периодами времени?

В настоящее время я использую boost::rational<std::uint64> отслеживать в моем приложении.

В основном у меня есть часы, которые работают в течение очень длительного периода времени и будут зависать от разных компонентов с разным временным разрешением, например, 1/50 с, 1/30 с, 1001/30000 с и т. Д. Я хочу поддерживать идеальную точность, т.е. нет с плавающей запятой. boost::rational хорошо работает для этой цели, однако я думаю, что было бы лучше использовать дизайн std::chrono::duration за это.

Моя проблема, хотя, как я могу использовать std::chrono::duration Вот? Поскольку он использует период времени компиляции, я не совсем понимаю, как я могу использовать его в моем сценарии, где мне нужно поддерживать точность?

2 ответа

Решение

Вам разрешено установить период 1 и использовать тип с плавающей запятой для Rep,

Я подозреваю, что вы можете сделать то же самое с boost::rational, но вам придется присмотреться std::chronoчто я не сделал. смотреть на treat_as_floating_point а также duration_values, Также попытайтесь выяснить, что означает стандарт под "арифметическим типом или классом, эмулирующим арифметический тип".

Можно разумно утверждать, что если boost::rational не эмулирует арифметический тип, тогда он не выполняет свою работу. Но это не обязательно означает, что на самом деле все std::chrono::duration надеется.

Если я понимаю ваш вопрос и если вы знаете все временные разрешения во время компиляции, то следующее будет делать то, что вы хотите. Вы можете определить правильный период тиков, используя common_type на всех ваших разных временных разрешениях, как показано ниже:

#include <cstdint>
#include <chrono>

struct clock
{
    typedef std::uint64_t                      rep;
    typedef std::common_type
    <
        std::chrono::duration<rep, std::ratio<1, 50>>,
        std::chrono::duration<rep, std::ratio<1, 30>>,
        std::chrono::duration<rep, std::ratio<1001, 30000>>
    >::type                                    duration;
    typedef duration::period                   period;
    typedef std::chrono::time_point<clock>     time_point;
    static const bool is_steady =              true;

    static time_point now()
    {
        // just as an example
        using namespace std::chrono;
        return time_point(duration_cast<duration>(steady_clock::now().time_since_epoch()));
    }
};

Это вычислит во время компиляции самый большой тиковый период, который будет точно представлять каждое из указанных вами разрешений. Например, с этими часами можно точно представить:

  • 1/50 с 600 тиками.
  • 1/30 с 1000 тиков.
  • 1001/30000 с 1001 тиков.

Код ниже осуществляет это clock и использует описанную здесь функцию "chrono_io", чтобы распечатать не только количество тактов во время выполнения ваших часов, но также и единицы времени компиляции вашего такта:

#include <iostream>
#include <thread>
#include "chrono_io"

int main()
{
    auto t0 = clock::now();
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    auto t1 = clock::now();
    std::cout << (t1-t0) << '\n';
}

Для меня это распечатывает:

633 [1/30000]seconds

Значение: было 633 такта между вызовами now() и единица измерения каждого тика составляет 1/30000 секунды. Если вы не хотите быть привязанным к "chrono_io", вы можете проверить единицы ваших часов с помощью clock::period::num а также clock::period::den,

Если ваши разные временные разрешения не являются информацией времени компиляции, то ваше текущее решение с boost::rational наверное лучше.

Другие вопросы по тегам