让类型变量double转换为类型变量float。如果变量double包含一个值NaN,则将其转换为NaN。如果变量double包含一个值Inf,则将其转换为Inf。如果变量double包含一个值-1e+50,则将其转换为-Inf。
这种行为是由 C++ 标准保证的,还是IEEE 754保证的?或者它是实现定义的行为,还是通常未定义的行为,一般来说不值得指望-1e+50转换-Inf为什么?
让类型变量double转换为类型变量float。如果变量double包含一个值NaN,则将其转换为NaN。如果变量double包含一个值Inf,则将其转换为Inf。如果变量double包含一个值-1e+50,则将其转换为-Inf。
这种行为是由 C++ 标准保证的,还是IEEE 754保证的?或者它是实现定义的行为,还是通常未定义的行为,一般来说不值得指望-1e+50转换-Inf为什么?
严格来说,标准没有定义 和 的维度
float,double但在我的回答中,我会假设它们具有不同的维度,分别代表 32 位和 64 位数据类型。因为
float可以容纳从±1.18×10^(−38) 到 ±3.4×10^38的数字,并且您尝试将其放入变量float中,该变量的double值无法精确表示的类型float,您会得到-inf.你会得到未定义的行为。-inf因此,不值得期待。我最初的回答是说你得到了未定义的行为,这是不正确的。如果我们试图适应
float一个无法在其中表示的数字,则会导致未定义的行为。以下是标准中的描述:C++14 标准[conv.double]
但这都是关于抽象实现的,我们有它非常具体(这是我的错误——我尝试了一个具体的实现来进行抽象描述并得出了错误的结论)。由于我对有效值的范围做出了假设
float,所以我采用了一个特定的实现——IEEE 754。既然我采用了这个实现,那么我需要从它开始,而不是从抽象开始。根据 IEEE 754,无穷大是类型的一部分,因此它的最大值和最小值不是它的分隔符。只是根据舍入规则将允许范围之外的所有内容减少到所需的值。所以,根据这条规则,如果你尝试用 表示
-1e+50,float那么它会变成-INF- 这是一个正常值float,并且当std::numeric_limits<float>::is_iec559等于true* 时保证它。那些。我们从标准中得到了这种情况:“源值在两个相邻的目标值之间,转换的结果是实现定义的对这些值中的任何一个的选择”。如果上述常数等于
false,那么问题的答案可能会有所不同,但也应该在具体实现的框架内考虑,因为 我们在问题中有一个具体的数字,如果没有实施方面的具体细节,我们无法考虑。总结一下:这种行为是否是未定义的行为,是否依赖于实现——这一切都取决于浮点类型的表示,不能在它之外考虑。
* 我没有找到文件本身的文字,但许多引用它的文件都说明了这一点。
顺便说一句,在 C 中,这更明确地说明:如果环境支持无穷大,则定义结果,并通过问题中的示例给出保证
-inf。这在 C11 标准[5.2.4.2.2/p5]中有所描述