最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Precision of chrono duration with double does not appear in format printing - Stack Overflow

programmeradmin1浏览0评论

In the following code:

using seconds = std::chrono::duration<long double, std::ratio<1, 1>>;
using namespace std::literals;

int main() {
    seconds s = 10ms + 10us + 10ns;
    std::print("from chrono {} | from count {:%Q}\n", s, s);
}

I get the print out:

from chrono 0.01001s | from count 0.01001001

See live example.

Why is the format for chrono passed directly in cropping the time this way? The chrono duration can represent the nanoseconds and clearly the format specification allows printing decimals. Why does it stop after 5 decimal places?

If i change it to:

 seconds s = 10ms + 10us + 123ns;
 std::print("from chrono {} | from count {:%Q}\n", s, s);

See live example

Then i get

from chrono 0.0100101s | from count 0.010010123

Which has more precision but is still wrong. There does not appear to be a format specifier that affects this (format specialisation).

What is the explanation for this behaviour?

In the following code:

using seconds = std::chrono::duration<long double, std::ratio<1, 1>>;
using namespace std::literals;

int main() {
    seconds s = 10ms + 10us + 10ns;
    std::print("from chrono {} | from count {:%Q}\n", s, s);
}

I get the print out:

from chrono 0.01001s | from count 0.01001001

See live example.

Why is the format for chrono passed directly in cropping the time this way? The chrono duration can represent the nanoseconds and clearly the format specification allows printing decimals. Why does it stop after 5 decimal places?

If i change it to:

 seconds s = 10ms + 10us + 123ns;
 std::print("from chrono {} | from count {:%Q}\n", s, s);

See live example

Then i get

from chrono 0.0100101s | from count 0.010010123

Which has more precision but is still wrong. There does not appear to be a format specifier that affects this (format specialisation).

What is the explanation for this behaviour?

Share Improve this question asked Jan 29 at 6:48 Fantastic Mr FoxFantastic Mr Fox 34k28 gold badges104 silver badges187 bronze badges 5
  • 2 It stops at six significant digits and doesn't output trailing zeros, i.e. it is the normal floating point output. You can specify the precision in the format. – molbdnilo Commented Jan 29 at 7:14
  • @molbdnilo Why does it choose 32bit floating point output though? It knows the type of the duration is double? If i print a double the same way (aka count) it gives me the correct precision. – Fantastic Mr Fox Commented Jan 29 at 22:05
  • @molbdnilo, in fact even if i print a double and float containing that number it still prints the right thing. Where does it specify that it stops at 6 significant digits? – Fantastic Mr Fox Commented Jan 29 at 22:07
  • @molbdnilo precision specifiers seem to be ignored for durations godbolt./z/jd3vhr9PG – Alan Birtles Commented Jan 30 at 12:29
  • precision specifiers do work with fmtlib godbolt./z/xYjfvoMva (though clang doesn't seem to be able to compile the duration prints?) – Alan Birtles Commented Jan 30 at 12:48
Add a comment  | 

1 Answer 1

Reset to default -2

This behavior is due to how the formatting and output functions work with std::chrono durations, particularly when used with floating-point durations like long double. The seconds type is defined as a std::chrono::duration<long double, std::ratio<1, 1>>. long double is a floating-point type, and floating-point numbers can only represent values with a certain precision. Even though you expect a high degree of precision (e.g., nanoseconds), the actual precision can be constrained by the internal representation of the floating-point type. The default behavior of std::chrono::duration when formatted in this way is that it rounds the printed value to a reasonable precision and does not output the trailing zeros. This is done for simplicity, to avoid excessively long outputs for values that don't need that much precision for most applications.

Some suggestions which you can try out:

  • Use std::setprecision to control the output precision

    Example:

    seconds s = 10ms + 10us + 10ns;
    std::cout << "from chrono " << std::fixed << std::setprecision(9) << s.count() << "s\n";  // Manually set precision
    
  • if your goal is to display the duration in a smaller time unit (e.g., nanoseconds) for greater precision, you can use std::chrono::duration_cast to convert the duration to a finer-grained unit, like nanoseconds.

    Example:

    auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(s);
    std::cout << "from chrono " << nanos.count() << "ns\n";
    
发布评论

评论列表(0)

  1. 暂无评论