我想这个转换不可能失败。所以
boost::numeric_cast<double>(long)
应该产生与普通演员相同的结果。
这是正确的吗?如果是这样,为什么
boost::numeric_cast
比普通演员慢?它正在做某种检查吗?
static_assert((1ull<<57ull)!=(1+(1ull<<57ull)));
static_assert((double)(1ull<<57ull)==(double)(1+(1ull<<57ull)));
boost numericcast 会抛出这一轮,就像上面的代码一样。
64 位整数可以表示一些 64 位双精度数无法表示的整数。 64 位双精度数在“指数”上花费位。
来自文档:
缺乏范围保留使得数字类型之间的转换容易出错。对于隐式转换和显式转换(通过
)都是如此。static_cast
检测数字类型转换时范围的丢失,如果无法保留范围则抛出异常。numeric_cast
所以看起来 boost 的数字转换做了一些额外的检查,并且可以抛出异常 - 所以它们并不总是与“常规转换”相同。
文档说
boost::numeric_cast
用于在不损失范围的情况下进行投射。 long
的范围不一定比 double
窄,因此 boost::numeric_cast<double>(long)
可能会产生与常规演员不同的结果。例如,一个实现可以具有 96 位 long
和 72 位 double
,且 double
范围非常小。这没有什么问题,它完全符合 C++,因为 C++ 中的类型没有固定大小,只有最小大小。请参阅 C++ 标准规定 int、long 类型的大小是多少?
此外,文档可能有点不清楚,因为
boost::numeric_cast
还阻止从目标类型中无法表示的值进行转换。出于显而易见的原因,浮点值不会将其所有位用于值的重要部分,并会为了精度而交换范围。因此,N 位 double
的精度将小于 N,等于 std::numeric_limits<double>::digits
/DBL_MANT_DIG
位。对于 IEEE-754 二进制 64,精度为 53 位,因此如果 long
值需要超过 53 位的有效数,那么显然它不能存储在 double
中。例如 0xABCDEF9876543210 = -6066929684898893296
有 60 位有效数,即第一个和最后一个 1 位之间的距离。转换为 double
时,它将四舍五入为 -6066929684898892800
。值的变化意味着 boost::numeric_cast
将失败。有些语言(例如 JavaScript)甚至有一个 MAX_SAFE_INTEGER
常量来表示这个
另请参阅