Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 std::chrono subtract now and min

Tags:

c++

chrono

I feel like I'm going a little crazy with this one, but it just doesn't make sense to me. In my mind, if I subtract the minimum time point from any time point returned from a now() call, I should always get a positive duration, but that doesn't happen.

#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;
}

Why does this print a negative integer and not a positive integer? (clang 3.3 or g++ 4.8.1)

like image 470
LorenVS Avatar asked Feb 15 '14 08:02

LorenVS


People also ask

What does std :: Chrono :: System_clock :: now return?

std::chrono::system_clock::now Returns a time point representing with the current point in time.

What is STD Chrono in C++?

(since C++11) Class template std::chrono::duration represents a time interval. It consists of a count of ticks of type Rep and a tick period, where the tick period is a compile-time rational fraction representing the time in seconds from one tick to the next.

What is std :: Chrono :: Time_point?

Class template std::chrono::time_point represents a point in time. It is implemented as if it stores a value of type Duration indicating the time interval from the start of the Clock 's epoch. Clock must meet the requirements for Clock or be std::chrono::local_t (since C++20).

What is boost chrono?

Chrono. The library Boost. Chrono provides a variety of clocks. For example, you can get the current time or you can measure the time passed in a process.


2 Answers

As has been pointed out this is the result of overflow. Remember that the minimum value a signed type can represent is about the same magnitude as the largest. If now is positive then the difference between now and min will clearly have greater magnitude than min, which means it has greater magnitude than the type's largest value can represent.

If you want to guarantee a positive duration then instead of using the minimum you could instead use a steady clock and then use the program start time as the base. The built-in clock durations are all specified such that a duration should be able to represent a range of at least a couple hundred years, so unless your program runs for longer than that you'll get positive durations.

Another option is to choose a clock where the epoch is known to be in the past and simply say

Clock::now().time_since_epoch();
like image 193
bames53 Avatar answered Oct 28 '22 08:10

bames53


You're overflowing the counter which, on my machine, is a 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;
}

Output:

-9223372036854775808
13924525439448122
-9209447511415327686
max of signed long long:9223372036854775807
like image 33
Marco A. Avatar answered Oct 28 '22 08:10

Marco A.