Search code examples
c++c++-chrono

Problem with std::chrono::duration convert


How I convert std::chrono::duration<long double, std::ratio<1, 1000000000>> in a std::chrono::nanoseconds in this example:

#include <chrono>

void main(void)
{
    auto ld = std::chrono::duration<long double, std::ratio<1, 1000000000>>(0.001);
    //std::chrono::nanoseconds ns = convertToNanoSec(ld); //How to do this?
}

Convert std::chrono::duration<long double, std::ratio<1, 1000000000>> in a std::chrono::nanoseconds


Solution

  • I suspect that there are two answers here:

    1. The literal answer to your question.
    2. The answer to the question you intended.

    The literal answer to your question is that you can use any of1

    • std::chrono::duration_cast
    • std::chrono::floor
    • std::chrono::ceil
    • std::chrono::round

    to convert any duration to any other duration. When converting from floating-point-based durations to integral-based durations I like to use round which rounds to nearest. This tends to minimize unexpected results due to the fact that the floating-point representation may not be able to exactly represent the value you're expecting.

    Example:

    auto ld = std::chrono::duration<long double, std::ratio<1, 1000000000>>(0.001);
    std::chrono::nanoseconds ns = std::chrono::round<std::chrono::nanoseconds>(ld);
    

    Use of local using directives or using declarations, combined with provided type aliases can make this more readable:

    auto ld = duration<long double, nano>(0.001);
    auto ns = round<nanoseconds>(ld);
    

    In both of these examples the results is 0 nanoseconds, which I'm guessing is not the answer you intended. The reason for this is that ld is holding 1/1000 of a nanosecond, not 1/1000 of a second.

    Thus my second answer:

    I'm guessing you have 0.001 seconds that you want to express as an integral number of nanoseconds (1,000,000). If that is the case then the first thing to do is convert the 0.001 long double to a long-double-based duration that represents seconds, not nanoseconds:

    auto ld = std::chrono::duration<long double>(0.001);
    

    And then proceed as before:

    auto ns = round<nanoseconds>(ld);
    

    Now ns holds a million nanoseconds.


    1 floor, ceil and round were introduced in C++17. Prior to that only duration_cast comes in the std toolbox, but you can find the rest in free, open source code.