我想知道,事件发生还剩多少时间。我正在使用boost :: chrono或std :: chrono。
基本上算法是这样的:
using std::chrono; // Just for this example
auto start = steady_clock::now();
seconds myTotalTime(10);
while(true){
auto remaining = start + myTotalTime - steady_clock::now();
seconds remainingSecs = duration_cast<seconds>(remaining);
if(remainingSecs.count() <= 0) return true;
else print("Remaining time = " + remainingSecs.count()); // Pseudo-Code!
}
现在可以(理论上)发生以下情况:start
接近时钟周期的末尾(IMO没有概念0
意味着什么,所以它可能是任意的。) />
然后start + myTotalTime
可能会溢出,减法可能会下溢。
即使像steady_clock::now() - start
这样简单的事情也可能下流。
对于无符号类型,这不是问题。如果它们是未签名的,则标准保证在溢出steady_clock::now() - start
的情况下我仍然获得now()
的正确数量的“单位”以及8位无符号的下溢减法:10 - 250 = 10 + 256 - 255 = 16
数学。
但签名类型的AFAIK over / underflow是未定义的行为。
我错过了什么吗?为什么使用signed而不是unsigned类型定义持续时间,尤其是time_points?
答案 0 :(得分:4)
这是一个简短的程序,您可以使用它来查看steady_clock
中任何平台剩余的范围(相对于现在):
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
using namespace std;
using days = duration<int, ratio<86400>>;
using years = duration<double, ratio_multiply<ratio<146097, 400>, days::period>>;
cout << years{steady_clock::time_point::max() -
steady_clock::now()}.count() << " years to go\n";
}
这将输出steady_clock
将溢出的年数。在几个不同的平台上运行几次之后,你会感到温暖的模糊感觉,除非你的程序运行超过几百年,否则你不必担心。
在我的平台上(这很常见),steady_clock
正在以纳秒为单位测量自启动以来的时间。
对我来说,这个程序输出:
292.127 years to go
任何平台和任何不能代表now()
而没有溢出的时钟都不太可能被广泛采用。
为什么用signed而不是unsigned类型定义持续时间,尤其是time_points?
使duration
和time_point
减法更容易出错。是的,如果你减去 unsigned_smaller - unsigned_larger ,你会得到一个明确定义的结果,但这个结果可能不是程序员所期望的答案(例子除外) of time_point +你给的持续时间。)
因此,1970年之前的日期时间可以用system_clock::time_point
表示。虽然未指定,但system_clock
正在衡量Unix Time(使用各种精确度),这是事实上的标准。这需要保留负值以表示1970-01-01 00:00:00 UTC之前的时间。我目前正试图将现有做法标准化。
相反,使用足够数量的位指定有符号整数表示,以使溢出成为罕见问题。纳秒精度保证在+/- 292年的范围内。较粗的精度将具有更大的范围。当此默认值不足时,允许使用自定义表示。
答案 1 :(得分:2)
我没有看到问题。你选择的单位不能满足你的需要吗?
在我的系统上(是的,我知道,但是)std :: chrono :: seconds定义为int64_t,所以假设选择了一个合理的纪元(!=大爆炸),它不会很快溢出。< / p>
其他的也是如此,但是以纳秒为单位擦掉了30位,很有可能出现溢出,剩下的33位给出/只有/ 270年左右。
time_point内部使用持续时间,因为它是自纪元以来的持续时间。原则上,如果您的纪元是1970年(Unix),您可能希望在此之前参考日期,因此必须进行签名。如果您的纪元是1600(Windows),您显然不能使用纳秒来表示当前时间点,这是一个可移植性问题。
您可以使用double来定义自己的持续时间,当然,其中范围被交换为分辨率,并且我在过去这样做是打印十进制第二时间戳的便捷方式。
如果您需要范围和分辨率,也可以定义更大的整数类。