这个问题的灵感来自于关于负无穷大的问题和关于浮点数总排序的另一个问题。
我的印象是,经过一些明智的律师处理,
-std::numeric_limits<float>::infinity()
保证在std::numeric_limits<float>::has_infinity
时有效,无论std::numeric_limits<float>::is_iec559
是否为true
。
但是在我发布支持负无穷大问题的答案之前,我需要解决一个附带问题:您是否可以以
infinity == -infinity
(它在射影中的工作方式)实现具有(负)无穷大的浮动空间),并且仍然兼容且有用。
现在,如果
-infinity
不小于所有其他浮点值,则它不会有用。但是,如果 infinity == -infinity
,则该值必须同时大于和小于所有其他浮点值。这打破了我们对实数的严格总排序(比较不能跨越无穷大,否则毫无用处),但正如有关总排序的问题所示,浮点数已经偏离了严格的总排序,因为NaN
,并且它们仍然被认为是完全有序的。
标准中是否有任何内容阻止了有意义的
-std::numeric_limits<float>::infinity()
的实施,同时也-std::numeric_limits<float>::infinity() == std::numeric_limits<float>::infinity()
?
不用说,这不是使用 IEEE754/IEC559 浮点的实现。在不使用 IEEE754/IEC559 的实现中,该标准的大部分内容都被排除在外。但考虑到这样的实现比母鸡的牙齿还罕见,我们需要坚持语言律师,而不是现有编译器所做的事情,我们认为合乎逻辑的事情,或者我们希望看到的事情。
似乎有可能存在正无穷大而不是负无穷大(反之亦然)。 [基础.根本]p13:
浮点类型可表示值的最小范围是该类型可表示的最大负有限浮点数到该类型可表示的最大正有限浮点数。此外,如果负无穷大可以用某种类型表示,则该类型的范围将扩展到所有负实数;同样,如果正无穷大可以用某种类型表示,则该类型的范围将扩展到所有正实数。
(这是由CWG2723添加的)
因为负无穷大和正无穷大是分开列出的,似乎并不暗示另一个的存在。
并从 C18、C++23 传递而来 [cmath.syn]p1:
标头
的内容和含义与C标准库标头<cmath>
相同,[...]<math.h>
和 C18 §7.12p4(“
<math.h>
”):
宏观
INFINITY
扩展为 float 类型的常量表达式,表示正或无符号无穷大(如果可用); 否则为在转换时溢出的 float 类型的正常量。
这个“无符号无穷大”与射影/复无穷大是同一回事,但在这两个标准中都没有再次提及。这似乎确实意味着它是“官方”支持的。
has_infinity
:
如果该类型具有正无穷大的表示。true
infinity
:
正无穷大的表示(如果有)。
因此,如果
has_infinity == true
,则 infinity()
为正无穷大。这并没有说明负无穷大(如果浮点类型只有无符号无穷大,则has_infinity
将是false
,并且numeric_limits<T>::infinity()
将没有意义)
关于排序无符号无穷大的观点,浮点类型不被认为对所有值都是完全排序的。事实上,
f1 <=> f2
返回一个std::partial_ordering
。仅当您将 std::less<float>{}
的域限制为不具有 float
或其他非全序值时,像 NaN
这样的东西才被视为全排序。
您可以实现一个具有无符号无穷大的奇异浮点系统,其比较类似于 NaN(或者可能会引发浮点异常),但
numeric_limits<T>::infinity
不会是那种无符号无穷大(INFINITY
可能是)。
特别是对于表达式
-std::numeric_limits<float>::infinity()
当 std::numeric_limits<float>::has_infinity
时,我们知道一定存在正无穷大,但如果存在负无穷大则不然。这很容易意味着 -
操作数的否定在生成的浮点类型中无法表示,这意味着它将是 UB。如果它不是 UB,它绝对不能等于正无穷大,因为它必须是负数。
当
INFINITY == -INFINITY
宏扩展到无符号无穷大时,INFINITY
是完全合理的。这只是意味着 -INFINITY
在技术上不是一种获得负无穷大的可移植方式,并且“无符号无穷大”与“正无穷大”或“负无穷大”是不同的。