5

我刚开始学习 Kotlin,在基本类型的文档中遇到了一个奇怪的句子:

-0.0 被认为小于 0.0

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

4

3 回答 3

7

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

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

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

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

于 2018-02-04T16:12:39.643 回答
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 对舍入的仔细注意,溢出, ETC。)。也许这在 Kotlin 文档的其他地方讨论过;我仍然对这个功能感到有些不安。

于 2021-07-17T06:13:20.693 回答
0

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

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

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

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

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

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

于 2021-07-17T07:08:01.367 回答