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

时间:2018-02-04 15:08:15

标签: kotlin ones-complement

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

  

-0.0被认为小于0.0

我理解他们的价值观在补码中并不相同,但我不知道如何在代码中使用它们。

3 个答案:

答案 0 :(得分:7)

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

同样,您希望地图与NaN匹配,尽管标准声明NaN!= NaN

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

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

答案 1 :(得分:0)

我也发现了这句话,很疑惑。这实际上与零有两种表示这一事实无关,因为(人们可能会认为)理论上这应该隐藏在实现中,使得 -0.0 == +0.0 为真(可能不是 ===),同样 - 0.0 < +0.0 和 +0.0 < -0.0 都是假的)。

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

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

当然,程序员在浮点数上使用相等时必须格外小心,但直到现在我一直认为诸如“if (!!x) return 1.0/x”之类的东西在某种程度上或多或少是安全的(鉴于 IEEE 对舍入、溢出等)。也许这在 Kotlin 文档的其他地方讨论过;我还是觉得这个功能有点不爽。

答案 2 :(得分:0)

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

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

我也完全不明白最后一段是什么意思。根据类型是否可静态确定来更改相等的语义是荒谬的。我无法猜测 Kotlin 设计师的想法,但它不可能是这样的;我只是完全不明白那一段中发生了什么。

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

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

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