【问题标题】:Outside the range of representable values when casting double to long long with UBSAN enabled在启用 UBSAN 的情况下将 double 转换为 long long 时超出可表示值的范围
【发布时间】:2020-09-04 17:35:38
【问题描述】:

在启用 UBSAN 的情况下编译以下代码会导致此错误:

运行时错误:值 9.22337e+18 超出了可表示的范围 'long long' 类型的值

double a = (double)LLONG_MAX; // or (double)LLONG_MAX - 1
long long b = (long long)a;

这是一个已知问题吗?我的理解是该值不在范围之外。

【问题讨论】:

  • double 存储的确切数字是多少?可能已经超出范围。
  • 它没有四舍五入:确切的数字是 9,223,372,036,854,775,807(这不在文档的范围之外)--en.wikibooks.org/wiki/C_Programming/limits.h
  • LLONG_MAX 有一个确切的数字十进制值,但随后您将其转换为 double 可能无法表示该确切数字,因此它会四舍五入。
  • 我会看看,谢谢@ChristianGibbons

标签: c++ c ubsan


【解决方案1】:

您看到的是预期行为。

LLONG_MAX 是您系统上的 64 位整数,需要 63 位来完全表示其值(因为使用一位来保存符号)。典型的 double(使用 IEEE 算法)只有 53 位精度。

当您将整数分配给双精度时,整数值需要为 converted 到双精度。当整数需要更多位来表示其值时,双精度数可以存储,这种转换将导致值的一些精度损失,这是通过舍入完成的。这是一个实现细节,如果这将向上或向下舍入,但根据 IEEE 算术规则,四舍五入将是最接近的。

因为在您的系统中 long 值被四舍五入,所以生成的 double 值无法存储在 long long 中,从而导致您的运行时错误。

【讨论】:

    猜你喜欢
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    • 2015-08-23
    • 2021-12-03
    • 2013-01-20
    相关资源
    最近更新 更多