为什么 std::chrono::time_point 不够大,无法存储 struct timespec?

2023-12-22

我正在尝试最近的std::chronoapi 和我发现在 64 位 Linux 架构和 gcc 编译器上time_point and duration类无法以最大分辨率(纳秒)处理操作系统的最大时间范围。事实上,相比之下,这些类的存储似乎是 64 位整数类型timespec and timeval它们在内部使用两个 64 位整数,一个表示秒,一个表示纳秒:

#include <iostream>
#include <chrono>
#include <typeinfo>
#include <time.h>

using namespace std;
using namespace std::chrono;

int main()
{
    cout << sizeof(time_point<nanoseconds>) << endl;                       // 8
    cout << sizeof(time_point<nanoseconds>::duration) << endl;             // 8
    cout << sizeof(time_point<nanoseconds>::duration::rep) << endl;        // 8
    cout << typeid(time_point<nanoseconds>::duration::rep).name() << endl; // l
    cout << sizeof(struct timespec) << endl;                               // 16
    cout << sizeof(struct timeval) << endl;                                // 16
    return 0;
}

在64位Windows(MSVC2017)上情况非常相似:存储类型也是64位整数。在处理稳定(又名单调)时钟时,这不是问题,但存储限制使得不同的 API 实现不适合存储更大的日期和更宽的时间跨度,从而为类似 Y2K 的错误创造了基础。问题是否得到承认?是否有更好的实施或 API 改进的计划?


这样做是为了让您获得最大的灵活性和紧凑的尺寸。如果需要超精细的精度,通常不需要很大的范围。如果您需要非常大的范围,通常不需要非常高的精度。

例如,如果您以纳秒为单位进行交易,您是否经常需要考虑超过 +/- 292 年?如果你需要考虑比这个更大的范围,那么微秒可以给你+/- 292thousand years.

苹果系统system_clock实际上返回微秒,而不是纳秒。那么这个时钟从1970年开始可以运行29.2万年,直到溢出。

窗户system_clock精度为 100 纳秒单位,因此范围为 +/- 29,200 年。

如果几十万年还不够,可以尝试毫秒。现在你的范围是+/- 292million years.

最后,如果你只是have纳秒精度可以持续数百年,<chrono>还允许您自定义存储:

using dnano = duration<double, nano>;

这为您提供了存储为纳秒的double。如果您的平台支持 128 位整数类型,您也可以使用它:

using big_nano = duration<__int128_t, nano>;

哎呀,如果你为timespec,你甚至可以使用that用于存储(但我不推荐)。

您还可以实现比纳秒更精细的精度,但这样做会牺牲范围。例如:

using picoseconds = duration<int64_t, pico>;

其范围仅为 +/- 0.292 年(几个月)。那么你do必须小心这一点。如果您有一个可以提供亚纳秒精度的源时钟,那么非常适合计时。

查看这个视频 https://www.youtube.com/watch?v=P32hvk8b13M欲了解更多信息<chrono>.

为了创建、操作和存储范围大于当前公历有效性的日期,我创建了这个开源日期库 https://howardhinnant.github.io/date/date.html这扩展了<chrono>提供日历服务的图书馆。该库以带符号的 16 位整数存储年份,因此范围为 +/- 32K 年。它可以这样使用:

#include "date.h"

int
main()
{
    using namespace std::chrono;
    using namespace date;
    system_clock::time_point now = sys_days{may/30/2017} + 19h + 40min + 10s;
}

Update

在下面的评论中提出了如何“标准化”的问题duration<int32_t, nano>转换为秒和纳秒(然后将秒添加到 time_point)。

首先,我对将纳秒填充到 32 位中持谨慎态度。该范围仅略高于 +/- 2 秒。但我是这样区分单位的:

    using ns = duration<int32_t, nano>;
    auto n = ns::max();
    auto s = duration_cast<seconds>(n);
    n -= s;

请注意,这仅在以下情况下有效n是积极的。正确处理负面情绪n,最好的做法是:

    auto n = ns::max();
    auto s = floor<seconds>(n);
    n -= s;

std::floor是随 C++17 引入的。如果你想早点拿到,可以从here http://howardhinnant.github.io/duration_io/chrono_util.html or here https://github.com/HowardHinnant/date/blob/master/date.h.

我偏爱上面的减法运算,因为我发现它更具可读性。但这也有效(如果n不是负数):

    auto s = duration_cast<seconds>(n);
    n %= 1s;

The 1s在 C++14 中引入。在 C++11 中,您必须使用seconds{1}反而。

一旦你有几秒钟(s),您可以将其添加到您的time_point.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 std::chrono::time_point 不够大,无法存储 struct timespec? 的相关文章

随机推荐

  • 使用裁剪工具进行图像裁剪的 Django 应用程序

    我需要一个在客户端裁剪图像的应用程序 我的意思是 使用像 Jcrop jquery 插件这样的裁剪工具 我找到了这个工具 django 图像裁剪器 https github com marazmiki django image croppe
  • CUDA/PTX 32 位与 64 位

    CUDA 编译器可以选择生成 32 位或 64 位 PTX 这些有什么区别呢 是不是像 x86 一样 NVidia GPU 实际上也有 32 位和 64 位 ISA 还是仅与主机代码有关 指针肯定是最明显的区别 http docs nvid
  • NanoHTTPD - 将 https 流转换为 http

    为了克服 Chromecast 对来自自认证 https 服务器 在我的例子中是 Subsonic 音乐服务器 进行流传输的限制 我正在利用已经作为我的 Android 应用程序的一部分运行的 NanoHTTPD 服务器实例 这个想法是从
  • 如何在 Dart 中将 RxInt 转换为 Int ||扑?

    我正在玩扑扑 我遇到错误并且没有得到任何正确的解决方案 在我的应用程序中 我有一些可观察的变量GetX https pub dev packages get控制器 当尝试应用某种格式然后在此处获取日志时 Exception caught b
  • Maven 3.0.4 NoSuchMethod:... java.lang.NoSuchMethodError:com.google.common.collect.ImmutableSet.copyOf(..)

    我已经安装了Maven 3 0 4 with Homebrew每当我运行mvn命令我得到以下信息 Exception in thread main java lang NoSuchMethodError com google common
  • OkHttp 对请求启用/禁用 gzip 压缩

    我在用着Retrofit管理我的请求并希望进行一些测试来检查使用或不使用 gzip 的请求大小 默认情况下OkHttp对请求执行 gzip 压缩 或者必须使用拦截器 https github com square okhttp wiki I
  • jQuery 文档就绪与窗口加载冲突?

    我正在尝试拼凑一个视频库 我正在使用 jQuery 制作滑出面板 这很简单 我还使用 jQuery 来滚动缩略图 他们都工作得很好 问题是我需要滚动缩略图在滑出面板内工作 但事实并非如此 我认为这与文档准备好和窗口加载两个功能有关 我不确定
  • Ruby 中引发异常与抛出异常有什么区别?

    Ruby 有两种不同的异常机制 Throw Catch 和 Raise Rescue 为什么我们有两个 什么时候应该使用其中一种而不是另一种 raise fail rescue and ensure handle errors 也称为例外情
  • 如何以编程方式更新客户商店信用

    我正在使用 Magento 版本 1 9 1 1 我需要更新客户的商店信用余额 我知道可以在 Magento 管理界面中执行此操作 但就我而言 我需要向服务器发出 HTTP 请求 并且实际上执行与通过 Magento 管理界面执行的操作相同
  • 将brew安装的库包含到XCode中

    我正在尝试使用 Raylib 创建游戏 我想使用 XCode 因为我认为库管理会像 Windows 上的 Visual Studio 一样简单 我安装了这个库brew install raylib 现在我尝试运行这个从 Raylib 网站复
  • apollo graphql 响应数据中未显示“Extensions”字段

    这里有一个可重现的例子 https github com stonecold123 typegraphql test Run app js并在操场上导航http localhost 4000 graphql http localhost 4
  • VBA 中的编辑距离 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有包含数据的 Excel 工作表 我想获取它们之间的 Levenshtein 距离 我已经尝试导出为文
  • 使用 Python 2.7 的 HTML 解析树

    我试图为下面的 HTML 表配置一棵解析树 但无法形成它 我想看看树结构是什么样的 有人可以帮助我吗 p class title b The Dormouse s story b p p class story Once upon a ti
  • Python:BASIC 中是否有相当于中、右、左的词?

    我想做这样的事情 gt gt gt mystring foo gt gt gt print mid mystring Help 切片来救援 def left s amount return s amount def right s amou
  • iText 通过检查 CRL 来验证签名

    我正在设置一个验证器 可以检查签名的有效性 我所做的签名基于 DSS 级别 LT 因此文档中内置了撤销检查 我现在遇到的问题是在我在iText中开发的验证器层面 它允许验证签名的有效性以及撤销信息的有效性 根据我的研究 IText 允许基于
  • 在 Vim 中查找 C++ 类成员的定义/引用

    我正在将 Vim 用于一个我已经开始从事的 C 项目 并且最近我花了很多时间浏览现有代码以掌握它的窍门 为了使浏览更容易 我在 Vim 中设置了 ctags 和 cscope 来跳转到定义并查找引用 然而 我发现他们都没有足够的智能来知道成
  • 具有错误字符容限的最长公共子串

    我在这里找到了一个脚本 在寻找最低公共子串时效果很好 但是 我需要它来容忍一些不正确 丢失的字符 我希望能够输入所需的相似性百分比 或者指定允许的丢失 错误字符的数量 例如 我想找到这个字符串 大黄色校车 该字符串内部 那天下午他们乘坐黄色
  • 在node.js中使用python模块

    是否可以创建一种胶水 使 python 模块 更具体地说 库绑定 可以在 Node js 中使用 一些数据结构可以直接映射到 V8 对象 例如数组 字典 更重要的是 这会是比手动或通过 FFI 更优雅的创建绑定的方式吗 简而言之 值得吗 试
  • 更改seaborn条形图中的色标

    我想对我的数据使用seaborn条形图 并根据Y轴的值使用色标 例如 在此图像中 颜色根据调色板从左到右变化 但我真正想要的是相同的配色方案 但 垂直 而不是 水平 这可能吗 我已经搜索并尝试设置hueY 轴参数 但它似乎不起作用 我该怎么
  • 为什么 std::chrono::time_point 不够大,无法存储 struct timespec?

    我正在尝试最近的std chronoapi 和我发现在 64 位 Linux 架构和 gcc 编译器上time point and duration类无法以最大分辨率 纳秒 处理操作系统的最大时间范围 事实上 相比之下 这些类的存储似乎是