为什么 Kotlin 认为负零小于正零

Why Kotlin considers negative zero less than positive zero

我刚开始学习 Kotlin,我在 basic types 的文档中看到了一个奇怪的句子:

-0.0 is considered less than 0.0

我知道它们的值在补码中不会相同,但我不知道如何在代码中使用它。

不遵循 IEEE 754 标准的擦除浮点数比较的主要目的是,当您在集合中使用浮点数并作为排序键时,您不想要 按照标准 等同来相互混合。例如,您不想将 -0.00.0 混合作为映射中的键(您可能希望这些键有两个不同的值)。

同样,尽管标准声明 NaN != NaN.

,但您希望地图将 NaN 与其自身相匹配

并且,当您对一组项目进行排序时,您希望 NaN 与其他数字正确排序,即使标准说它与其他元素无法比较(遵循此处的标准甚至可能会破坏排序算法)。

请注意,这些规则仅适用于对象不是静态已知属于浮点类型的情况,这实际上与通用用例和集合相匹配。相反,数学用例通常直接使用数字类型(而不是将它们擦除为 Any 或类型参数),因此应用 IEEE 754 规则。

那句话我也找到了,百思不得其解。它实际上与零有两个表示这一事实几乎没有关系,因为(有人可能认为)理论上这应该隐藏在实现中,这样 -0.0 == +0.0 为真(可能不是 ===),同样 - 0.0 < +0.0 和 +0.0 < -0.0 均为假)。

然而,声明 -0 < +0 有一些很好的理由,尽管通常这些理由很模糊。 IEEE 754 标准规定了哪些应该 return 从什么开始编辑,并且还有用于舍入模式等的剩余(通常可设置,但通常也是全局的)控制开关,以及 (IIRC) 也用于控制是否 -0.0 < + 0.0 或 ==.

我敢肯定 Kotlin 的人们已经彻底考虑过了(<- 绕口令),因为如果没有大量的深思熟虑和经验,没有人会以这种方式设计语言功能。我可以想象程序员在某些情况下会对此感到非常困惑(例如,在多项式中找到虚假的额外根等),但如果程序员对 IEEE 有足够的了解,并且了解区别出现的地点和时间,那么它似乎不应该引起太多许多问题(除了跳过文档的那部分的程序员!)。

当然,程序员在浮点数上使用相等性时必须格外小心,但直到现在我一直认为“if (!!x) return 1.0/x”之类的东西或多或少是安全的(考虑到 IEEE 对舍入、溢出等的仔细关注)。也许这在 Kotlin 文档的其他地方讨论过;我对这个功能还是有点反胃。

我完全不明白上面的第一个答案,虽然我承认我是 Kotlin 的新手。

我不知道“擦除浮点比较”是什么意思,但我假设它意味着 -0.0 != +0.0 的决定。我将其视为实施决定,而不是擦除。

我也完全不明白最后一段是什么意思。根据类型是否可静态确定来更改类型的相等性语义是荒谬的。我猜不出 Kotlin 设计师的想法,但不可能是这样的;我根本不明白那段话是怎么回事。

此外,违反 IEEE 数字以允许浮动映射键,或提供额外的标记或标志或键值,是一种奇怪的优先级倒置。这就是 NaN 的用途。违反如此广泛使用的标准需要非凡的动力,而上面的第一个答案似乎错过了那条船。

如果您需要玩这种奇怪的游戏,最好使用底层的 32、64 或 128 位位串作为密钥。在 45 年的实时数值处理中,我什至从未想过用浮点数来索引地图,尽管我实际上可以想象它(但没有改变标准来适应这种混乱)。

也许我出去吃午饭了,但这里似乎某处严重脱节。