浮点数.NaN == 浮点数.NaN

Posted

技术标签:

【中文标题】浮点数.NaN == 浮点数.NaN【英文标题】:Float.NaN == Float.NaN 【发布时间】:2012-03-09 15:27:18 【问题描述】:

为什么这个比较给了我“假”?我查看了源代码,Float.NaN 被定义为

/** 
 * A constant holding a Not-a-Number (NaN) value of type
 * <code>float</code>.  It is equivalent to the value returned by
 * <code>Float.intBitsToFloat(0x7fc00000)</code>.
 */
public static final float NaN = 0.0f / 0.0f;

编辑:令人惊讶的是,如果我这样做:

System.out.println("FC " + (Float.compare(Float.NaN, Float.NaN)));

它给了我0。所以Float.compare() 确实认为 NaN is 等于它自己!

【问题讨论】:

【参考方案1】:

使用 Float.isNaN 检查 NaN 值。

【讨论】:

@Rolfツ 没什么可补充的,很简单。【参考方案2】:

因为 Java 实现了 IEEE-754 浮点标准,该标准保证与 NaN 的任何比较都将返回 false(!= 除外,它返回 true)

这意味着,您无法以通常的方式检查浮点数是否为 NaN,因此您可以将两个数字重新解释为整数并进行比较,或者使用更聪明的解决方案:

def isNan(val):
     return val != val

【讨论】:

!= 比较除外,它返回 true 您实际上可以通过这种方式测试 NaN!如果x==x 为假,则 x 为 NaN。 你也可以使用静态的Float.isNaN(float)(Double 也有它的版本)。 我想知道原因是什么?我理解将 NaN 视为既不大于、等于也不小于其他任何值的基本原理,但 x==y 最明智的含义是“x 与 y 无法区分”,并且如果 x 和 y 恰好都是 NaN这种说法是正确的。我想不出任何明智的“问题”可以用 IEEE 指定的平等规则来回答。 @supercat 我相信 !(NaN == Nan) 的原因是因为 NaN 可以用来表示很多东西。例如,(3.0/0.0) == (1.0/0.0) 吗?这很难明确地说是,所以我认为这就是为什么他们不能平等比较。【参考方案3】:

我只需要说:Wikipedia About NaN。

写得很清楚。有趣的是,通用标准的浮点 NaN 是这样表示 NaN 的:

s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

s 是符号(负或正),1 是指数,x 被认为是有效载荷。

查看负载时,NaN 不等于任何 NaN,作为开发人员,负载的这些信息很少会引起您的兴趣(例如复数)。

另一件事是,在标准中他们有信号和相当的 NaN。信号 NaN (sNaN) 表示应该引发异常反应的 NaN。它应该用来大声说你的方程式有问题。安静的 NaN (qNaN) 是静默传递的 NaN。

创建信号的 sNaN 被转换为 qNaN,以便在后续操作中不再产生任何信号。请记住,某些系统将 i^0 = 1 定义为 NaN^0 = 1 成立的常数。所以有些情况下人们用 NaN 进行计算。

所以最后我会选择这个:qNaN != sNaN 但这是内部的,用户无法观察到(你无法检查)。将付款和符号混合在一起(是的,您可以有负数和正数 NaN),在我看来,总是返回 NaN!= NaN 看起来是一个更明智的选择,我终于学会了欣赏 -> 我永远不会抱怨或怀疑再次讨论 NaN 的不等式。赞美那些考虑周到的人给我们这么好的标准!

顺便说一下:Java 使用负数为 0 的正 NaN(所有 x 都是零)。

【讨论】:

复数与有效载荷有什么关系? @MarkDickinson,***页面建议“使用 sNaN 作为更复杂对象的占位符,例如 […] 复数”

以上是关于浮点数.NaN == 浮点数.NaN的主要内容,如果未能解决你的问题,请参考以下文章

元组列表(字符串,浮点数)与 NaN 如何获得最小值?

如何在 c 中产生 NaN 浮点数?

ZeroDivisionError 整数异常,Nan 浮点数

将 NAN 浮点数转换为 int 的问题

生成 n 个不是 ∞ 或 NaN 的不同浮点数(在 Go 中)

IEEE754 浮点数系统中的 NaN 和 +-INF