std::chrono::duration_cast 总是向下截断(对正数即向零截断),不是四舍五入或向上取整;例如 1999ms 转 seconds 得 1s,-1999ms 得 -1s;其本质是安全的整数除法截断,确保结果不超过原始值。

std::chrono::duration_cast 会截断还是四舍五入?
它**总是向下截断(truncation)**,不是四舍五入,也不是向上取整。这是最容易误判的地方——比如把 1999ms 转成 seconds,结果是 1s,不是 2s。
原因在于 duration_cast 的语义是“安全向下取整”,确保转换后的时间值不会超过原始持续时间。它的底层行为等价于整数除法向零截断(对正数即向下取整)。
- 若需四舍五入,得手动加半单位再 cast:
duration_cast<seconds>(ms + milliseconds(500))</seconds> - 若需向上取整,用
ceil需配合duration的count()和period手动算,或借助std::ceil+double转换(但会损失精度) - 负数时注意:-1999ms → -1s(仍是向零截断),不是 -2s
为什么 duration_cast<milliseconds>(seconds{2}) 是合法的,但反过来可能溢出?
从大单位转小单位(如 seconds → milliseconds)本质是乘法,可能超出目标类型的 rep 范围;从小单位转大单位(如 milliseconds → seconds)是除法,更安全。
例如:duration_cast<milliseconds>(hours{100000})</milliseconds> 在 int 作 rep 时大概率溢出(100000 小时 ≈ 3.6e8 秒 = 3.6e11 毫秒 > INT_MAX)。
立即学习“C++免费学习笔记(深入)”;
- 编译器通常不报错,运行时行为未定义(常见为静默回绕)
- 可用
duration::max()和duration::min()做前置检查,但开销大,生产环境慎用 - 更稳妥的做法:用更大
rep类型,比如duration<long long milli></long>接收seconds转换结果
在跨线程或高精度计时中,cast 到 nanoseconds 为什么有时反而不准?
不是 duration_cast 不准,而是源头精度不足。比如 steady_clock::now() 在 Windows 上实际分辨率常为 15–16ms(由 QueryPerformanceCounter 底层决定),此时即使 cast 到 nanoseconds,低位数字也是补零,无实际意义。
真正影响精度的是时钟本身的 period,而非 cast 行为。
- 检查时钟精度:
using R = decltype(steady_clock::now().time_since_epoch())::period; static_assert(R::num == 1 && R::den == 1000000000, "not nanosecond clock"); -
system_clock在某些平台甚至只有秒级精度(老系统),cast 成nanoseconds同样无效 - 若需亚毫秒级测量,优先确认硬件和 OS 支持,而不是依赖 cast
std::chrono::duration_cast 和隐式转换的区别在哪?
隐式转换只允许在**可无损表示**的前提下发生,比如 seconds → milliseconds(因为 1s = 1000ms,整除无余);而 milliseconds → seconds **不允许隐式转换**,必须显式 duration_cast。
这是类型安全的设计:防止意外丢失精度。
- 以下合法:
milliseconds ms = seconds{5}; // 5000ms - 以下编译失败:
seconds s = milliseconds{5500}; // error: no implicit conversion - 必须写:
seconds s = duration_cast<seconds>(milliseconds{5500}); // s.count() == 5</seconds> - 哪怕两个 duration 的
rep类型相同、比例是整数倍,也必须 cast(如microseconds→nanoseconds)


















