【发布时间】:2022-11-16 11:08:22
【问题描述】:
正如标准所定义的那样,浮点转换是两种不是提升的浮点类型之间的转换。
最简单的例子是double到float:
double d = 0.1;
float f = d;
标准说[conv.double]:
浮点类型的纯右值可以转换为另一种浮点类型的纯右值。 如果源值可以在目标类型中精确表示,则转换的结果就是该精确表示。 如果源值在两个相邻的目标值之间,则转换的结果是实现定义的选择这些值中的任何一个。 否则,行为未定义。
允许作为浮点提升的转换被排除在浮点转换集中。在我上面的示例中,源值不能在目标类型中准确表示。
d的值是0.10000000000000001,而f的值(很可能)是0.10000000149011612,事实上,如果您将f转换回double,则不等于d。但是,此源值介于两个相邻的目标值之间:f和先前可表示的float值0.099999994039535522。所以f的值可以是这些值中的任何一个,但是因为0.10000000149011612比0.099999994039535522更接近0.10000000000000001,所以这可能是实现选择的值。我的问题是关于最后一个案例:
否则,行为未定义。
是否存在转换为未定义行为的任何值?由于浮点类型具有 +infinity 和 -infinity 的表示形式,因此我假设不存在任何未完全表示或位于两个相邻目标值之间的源值:任何
double值要么是精确的float值(包括NaN) 或介于 -infinity 和 +infinity 之间,在这种情况下它位于两个相邻的float值之间。那么这个“否则”的案例有什么意义呢?此处是否涵盖被视为浮点但不是
float、double或long double的奇异类型?float、double和long double之间的转换会导致未定义的行为吗?
【问题讨论】:
-
IANALL,“否则,行为未定义”。可执行定义(良好定义),作为一个扩大到标准。这可能会使您的程序在您的平台上具有可靠的、可预测的行为,但可能不像人们喜欢的那样可移植(这可能会在未来咬到你,就像我一样)。
-
@Eljay 问题不是“未定义行为是什么意思”,而是“你怎么可能得到那个说它是未定义行为的案例”。
-
C++ 标准不要求每个浮点类型都支持
+inf或-inf或NaN。我怀疑这个“未定义”子句会处理一个假设的平台,其中double持有无穷大被转换为不支持无穷大的float。 -
float和double不必是 IEEE 754 浮点类型。不确定是否存在不同的编码,您会落入 UB 案例,但标准已根据在存在 ab 异常的情况下的行为进行了编纂。 -
@DrewDormann 好的,我通过查看
std::numeric_limits<T>::has_infinity意识到了这一点。任何不支持无穷大的浮点类型的例子?在这种情况下,即使只是一个大的double(不是 +inf)转换为没有 +inf 的float也会结束。
标签: c++ floating-point language-lawyer