根据单个持续时间和比率计算两个持续时间的正确方法

Correct way to calculate two durations from a single duration and ratio

本文关键字:持续时间 两个 方法 单个 比率 计算      更新时间:2023-10-16

我已经实现了一种方法,使用std::chrono::duration值和占空比float给定的周期来计算开启和关闭时间的周期行为。这显示在下面的代码块中。持续时间和占空比的值只在运行时提供,所以我认为使用std::ratio是不可能的。有人能建议一种更清洁的方式来实现这一点吗?

PeriodicPulse(const Period period, const float duty): mRunning(false)
{
if (duty < 0 || duty > 1) {
throw std::runtime_error("Duty value should be between 0-1.");
}
auto tempTime = std::chrono::duration<float, decltype(period)::period>(period.count() * duty);
mOnTime = std::chrono::duration_cast<decltype(mOnTime)>(tempTime);
tempTime = std::chrono::duration<float, decltype(period)::period>(period.count() * (1 - duty));
mOffTime = std::chrono::duration_cast<decltype(mOffTime)>(tempTime);
}

您的代码对我来说很好,尤其是当您的测试显示它正在做您想要的事情时。下面我提供了一些风格上的清理,并将构造函数放在PeriodicPulse:的上下文中

struct PeriodicPulse
{
using Duration = std::chrono::milliseconds;
bool mRunning;
Duration mOnTime;
Duration mOffTime;
template <class Rep, class Period>
PeriodicPulse(const std::chrono::duration<Rep, Period> period, const float duty)
: mRunning(false)
{
if (duty < 0 || duty > 1) {
throw std::runtime_error("Duty value should be between 0-1.");
}
using namespace std::chrono;
duration<float, Period> tempTime = period * duty;
mOnTime = duration_cast<Duration>(tempTime);
tempTime = period * (1 - duty);
mOffTime = duration_cast<Duration>(tempTime);
}
};
  • 我已经将Period重命名为std::chrono::duration<Rep, Period>,以表明它实际上应该具有类型duration,但使用变量名period来描述持续时间的功能。这也限制了(我假设的)过于通用的模板参数。(我的假设可能不正确)

  • 当在函数范围内时,我发现重复使用std::chrono::过于冗长且难以阅读。我更喜欢using namespace std::chrono;本地函数。你可能会有不同的感受。

  • 我替换了:


auto tempTime = std::chrono::duration<float, decltype(period)::period>(period.count() * duty);

带有:

duration<float, Period> tempTime = period * duty;

这将重用重写参数类型中的Period,并避免不必要地使用.count()成员函数。

  • 对于mOnTimemOffTime的分配,我创建了一个Duration别名,这样就不必说decltype(mOnTime)了。decltype(mOnTime)没有错,我只是觉得Duration在这种情况下可读性更强,而且我仍然可以在一个地方更改这些成员的类型。

  • 当给tempTime第二个值时,duration_cast是不必要的,因为存在到基于浮点的持续时间的隐式转换。我再次避免了.count()成员功能,以便保持在<chrono>型系统的类型安全保护范围内。

我这样测试:

#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using date::operator<<;
using namespace std;
using namespace std::chrono;
using P = duration<int, ratio<1, 30>>;
PeriodicPulse p{P{3}, .2};
cout << p.mOnTime << 'n';
cout << p.mOffTime << 'n';
}

输出:

20ms
80ms

这和我用你的原始代码得到的答案是一样的。

不需要使用"date/date.h"。这只是我懒洋洋地流p.mOnTimep.mOffTime