【问题标题】:How to get the average of several chrono::time_points如何获得几个 chrono::time_points 的平均值
【发布时间】:2018-01-11 17:42:58
【问题描述】:

求几个数的平均值的公式当然是众所周知的:

而且这个公式可以很容易地用来得到chrono::durations的平均值:

template <class Rep0, class Period0>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0)
{
    return d0;
}

template <class Rep0, class Period0, class ...Rep, class ...Period>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0,
    const std::chrono::duration<Rep, Period>& ...d)
{
    return d0 + sum(d...);
}

template <class ...Rep, class ...Period>
auto
avg(const std::chrono::duration<Rep, Period>& ...d)
{
    return sum(d...) / static_cast<std::common_type_t<Rep...>>(sizeof...(d));
}

但是chrono::time_points 不能相互添加。我如何平均time_points?

【问题讨论】:

    标签: c++ c++14 chrono


    【解决方案1】:

    首先假设您可以添加time_points,然后操纵公式以消除这些添加:

    首先从总和中分离出t1

    接下来都加t1

    因素和重新排列:

    然后,由于您减去 t1 的次数与求和的次数相同,因此您可以将其包含在总和中:

    现在你在求和durations 而不是 time_points!由于我们已经有了一个求和durations 的函数,所以平均time_points 可以很容易地建立在它之上:

    template <class Clock, class Duration0, class ...Duration>
    auto
    avg(const std::chrono::time_point<Clock, Duration0>& t0,
        const std::chrono::time_point<Clock, Duration>& ...t)
    {
        constexpr auto N =
            static_cast<std::common_type_t<typename Duration0::rep,
                                           typename Duration::rep...>>(1 + sizeof...(t));
        return t0 + sum((t - t0)...) / N;
    }
    

    平均单个time_point 是一种特殊情况,因为durations 的sum 不处理求和零durations(单位是什么?)。因此很容易添加这种情况的重载:

    template <class Clock, class Duration0>
    auto
    avg(const std::chrono::time_point<Clock, Duration0>& t0)
    {
        return t0;
    }
    

    这是用 C++14 编写的。它可以用 C++11 编码,使用 trailing return type declaration 语法,更冗长,但完全可行。

    【讨论】:

    • 如果有人想在这背后进行数学讨论,持续时间是向量空间中的向量(它们支持缩放、0 和加/减),而时间点是仿射空间中的点(它们支持 仿射组合或“重心”,基本上是加权平均值)。实数也是一个向量空间,所以我们对它们的操作在向量空间中是有意义的(并且重载是有意义的)。我们没有仿射空间这样的原始数学概念,因此可用的符号更糟糕,并且没有简单的重载运算符。
    • sum(t0 - t0, (t - t0)...) 处理空箱是另一种选择。
    • 这有一个微妙的错误。如果rep 有符号,则t0 + sum((t - t0)...) / (1 + sizeof...(t)) 是混合算术,因为size_t 是无符号类型。如果t0 大于平均值,则sum 将为负数。 std::duration&lt;std::int64_t&gt;::operator/(size_t) 将使用通用类型,对于 64 位 size_t 将导致回绕到非常长的持续时间。
    • 好收获。我会加入一个 static_cast。
    猜你喜欢
    • 2012-03-18
    • 1970-01-01
    • 2022-08-14
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 2015-09-11
    相关资源
    最近更新 更多