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

时间:2017-11-18 10:06:14

标签: c++ chrono

我已经实现了一种方法来计算周期性行为的开启和关闭时间,使用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);
}

1 个答案:

答案 0 :(得分:0)

您的代码对我来说很好,特别是如果您的测试显示它正在执行您想要的操作。下面我提供了一些风格清理,并且我将构造函数放在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>,表示实际上预计会有类型持续时间,但使用变量名称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在这种情况下更具可读性,我仍然可以在一个地方更改这些成员的类型。

  • 在给duration_cast第二个值时,
  • tempTime不是必需的,因为存在隐式转换为基于浮点的持续时间。我再次避免了.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时很懒惰。