1

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

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

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

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

4

1 回答 1

4

您所看到的是预期的行为。

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

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

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

于 2020-05-18T21:43:41.317 回答