В настоящее время я использую boost::rational<std::uint64>
отслеживать в моем приложении.
В основном у меня есть часы, которые работают в течение очень длительного периода времени и будут зависать от разных компонентов с разным временным разрешением, например, 1/50 с, 1/30 с, 1001/30000 с и т. Д … Я хочу поддерживать идеальную точность, то есть без плавающей запятой. boost::rational
хорошо работает для этой цели, однако я думаю, что будет лучше использовать дизайн std::chrono::duration
за это.
Моя проблема, хотя, как я могу использовать std::chrono::duration
Вот? Поскольку он использует период времени компиляции, я не совсем понимаю, как я могу использовать его в моем сценарии, где мне нужно поддерживать точность?
Вам разрешено установить период 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()));
}
};
Это вычислит во время компиляции самый большой тиковый период, который будет точно представлять каждое из указанных вами разрешений. Например, с этими часами можно точно представить:
Код ниже осуществляет это 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
наверное лучше.