繁体   English   中英

C++11 std::chrono 现在减去最小值

[英]C++11 std::chrono subtract now and min

我觉得我对这个有点疯狂,但这对我来说没有意义。 在我看来,如果我从now()调用返回的任何时间点中减去最小时间点,我应该总是得到一个正的持续时间,但这不会发生。

#include <chrono>
#include <iostream>

typedef std::chrono::steady_clock myclock;

int main(int argc, char **argv) {
        myclock::time_point min = myclock::time_point::min();
        myclock::time_point now = myclock::now();
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(now - min).count();
        std::cout << millis << std::endl;
}

为什么这会打印负 integer 而不是正 integer? (clang 3.3 或 g++ 4.8.1)

如前所述,这是溢出的结果。 请记住,有符号类型可以表示的最小值与最大值大致相同。 如果now为正,则nowmin之间的差异将明显大于min大小,这意味着其大小大于类型的最大值可以表示的大小。

如果要保证正时长,则可以使用稳定的时钟,然后以程序开始时间为基准,而不是使用最小值。 都指定了内置时钟持续时间,因此持续时间应至少可以代表几百年的范围,因此,除非您的程序运行的时间长于肯定的持续时间。

另一种选择是选择一个已知时代的时钟,然后简单地说

Clock::now().time_since_epoch();

的计数器溢出了 ,在我的机器上,这是一个有signed long long

#include <chrono>
#include <iostream>
#include <limits.h>
using namespace std;

typedef std::chrono::steady_clock myclock;

int main(int argc, char **argv) {
    myclock::time_point min = myclock::time_point::min();
    long long minl = reinterpret_cast<long long&>(min);
    cout << reinterpret_cast<long long&>(min) << endl;

    auto now = myclock::now();
    long long nowl = reinterpret_cast<long long&>(now);
    cout << reinterpret_cast<long long&>(now) << endl;

    cout << (nowl-minl) << endl;

    cout << "max of signed long long:" << LLONG_MAX << endl;

    auto millis = std::chrono::duration_cast<std::chrono::seconds>(now - min).count();
    //std::cout << millis << std::endl;
}

输出:

-9223372036854775808
13924525439448122
-9209447511415327686
max of signed long long:9223372036854775807

这是我想发生的事情(从我在Apple-llvm 5.0调试器中观察到的结果):

myclock::time_point::min()返回最早的时间点,通常在内部由整数类型表示,比如long long int 这种类型的最小值通常是numeric_limits<long long int>::min ,它是-2 ^ 63。 此值很特殊,如果您将其取反,则通过整数溢出得到相同的值(因为最大long long int为2 ^ 63 -1):

-(-2 ^ 63)== 2 ^ 63 ==(2 ^ 63-1)+ 1 == -2 ^ 63(通过溢出)

减法也适用相同的逻辑。
所有这一切都表明整数溢出使(now - min)实际上等于(now + min) ,这必然是负数。

一些读者(比如我自己)可能已经来到这里,想要保证某个时间点已经过期,无论延迟如何。 这可能写成

//Init to far in the past so that on first run we perform the action
myclock::time_point prev_time = myclock::time_point::min(); 

// Compare current time with the past
myclock::time_point now = myclock::now();
auto delay = std::chrono::duration_cast<std::chrono::milliseconds>(1000);
if ((now - prev_time) > delay)
{
   //This does not happen?
}

正如在其他答案中所解释的,这是由于(now - prev_time)计算产生的正数大于可以存储的正数时溢出,因此环绕为负数。 这可以通过更改计算顺序来解决,以避免可能溢出的中间值:

if ((now - delay) > prev_time)
{
   //This works
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM