减法、浮动和duration_cast [重复]

问题描述 投票:0回答:1

假设我们有一个以纳秒为单位的时间戳,我们需要从中减去 2.5 秒。所以我创建了这样的代码:

nanoseconds current_ts{1645546551805673592};                            

float diff = 2.5;
nanoseconds target_ts = duration_cast<nanoseconds>(current_ts - (seconds{1} * diff));

但它返回的是

1645546549305673592
,而不是预期结果 (
1645546556876652544
)。经过一些实验,我发现问题在某种程度上与
float
类型有关,因为如果我将其更改为 double ,它就可以正常工作。如果我将
current_ts
移到
duration_cast

之外,它也可以正常工作

为什么会发生这种情况?跟float精度有关系吗?

这是最小的例子:

#include <chrono>
#include <iostream>
#include <list>


int main() {
  using namespace std::chrono;


  nanoseconds current_ts{1645546551805673592};
  float context_pre_event_image_sec_ = 2.5;
  nanoseconds target_ts = current_ts - duration_cast<nanoseconds>((seconds{1} * context_pre_event_image_sec_));
  nanoseconds target_ts_2 = duration_cast<nanoseconds>(current_ts - (seconds{1} * context_pre_event_image_sec_));

  std::cout << current_ts.count() << std::endl;
  std::cout << target_ts.count() << std::endl;
  std::cout << target_ts_2.count() << std::endl;
}

第二个输出是预期的,第三个是意外的

c++ c++-chrono
1个回答
1
投票

std::duration
对象由
Period
(表示为秒的分数)和
Rep
(任意数字类型)参数化。
operator-
std::duration
使用
std::common_type
辅助模板类型来推导出周期的最佳类型(直观上,最大公约数)和
Rep

对于

Rep
,使用以下规则:

如果

std::decay<decltype(false ? std::declval<T1>() : std::declval<T2>())>::type
是有效类型,则 [std::common_type] 的成员类型表示该类型

在您的情况下,T1 和 T2 分别是

int64_t
float
。三元运算符的类型是对两种类型应用隐式转换的结果,这又是
float

当然,浮点数无法准确表示预期结果。您可以通过将 1645546549305673592 插入这个方便的 IEEE-754 工具来快速验证这一点。

© www.soinside.com 2019 - 2024. All rights reserved.