在Java中,NaN是什么意思?

时间:2010-04-11 17:57:47

标签: java nan

我有一个程序试图将double缩小到所需的数字。我得到的输出是NaN

NaN在Java中意味着什么?

11 个答案:

答案 0 :(得分:138)

取自this page

  

“NaN”代表“不是数字”。 “南”   如果是浮点则产生   操作有一些输入参数   导致操作产生   一些未定义的结果。例如,   0.0除以0.0是算术上未定义的。取平方根   负数也未定义。

答案 1 :(得分:16)

NaN表示“非数字”,基本上是IEE 754 floating point标准中特殊浮点值的表示。 NaN通常意味着该值不能用有效的浮点数表示。

当转换的值是其他值时,转换将导致此值,例如,在转换不表示数字的字符串时。

答案 2 :(得分:12)

NaN表示“非数字”,是浮点数的未定义运算的结果,例如将零除以零。 (请注意,虽然在数学中通常不会将非零数除以零,但它不会导致NaN,但会产生正或负无穷大。)

答案 3 :(得分:5)

NaN表示“不是数字”。它是一个特殊的浮点值,表示操作的结果未定义或不能表示为实数。

有关此值的更多说明,请参阅here

答案 4 :(得分:5)

NaN代表非数字。它用于表示数学上未定义的任何值。比如将0.0除以0.0。 您可以在此处查看更多信息:https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm

如果您需要更多帮助,请在此处发布您的计划。

答案 5 :(得分:4)

NaN =不是数字。

答案 6 :(得分:4)

意味着不是数字。 它是许多编程语言中不可能的数值的常见表示。

答案 7 :(得分:3)

不是Java人,但在JS和其他语言中我使用它的“非数字”,这意味着某些操作导致它变得不是有效数字。

答案 8 :(得分:3)

字面意思是“不是数字”。我怀疑你的转换过程有问题。

查看this reference

上的非编号部分

答案 9 :(得分:3)

不是有效的浮点值(例如,除以零的结果)

http://en.wikipedia.org/wiki/NaN

答案 10 :(得分:1)

最小的可运行示例

首先要知道的是,NaN的概念是直接在CPU硬件上实现的。

所有主要的现代CPU似乎都遵循IEEE 754来指定浮点格式,而NaN(只是特殊的浮点值)就是该标准的一部分。

因此,该概念在所有语言中都将非常相似,包括Java,Java只是将浮点代码直接发送到CPU。

在继续之前,您可能需要先阅读我写的以下答案:

现在进行一些Java操作。大部分不在核心语言中的重要功能都位于java.lang.Float内部。

Nan.java

public class FirebaseAuthenticator: IFirebaseAuthenticator
{

    public void RegisterOrLoginWithMobileNumber(string MobileNumber)
    {

        Activity activity = MainActivity.CurrentActivityRef;
        PhoneAuthCredentialCallBack callBack = new PhoneAuthCredentialCallBack();
        PhoneAuthProvider.Instance.VerifyPhoneNumber(MobileNumber,
                                                                  60,
                                                                  TimeUnit.Seconds,
                                                                  activity, callBack
                                                                  );

    }
}

GitHub upstream

运行方式:

import java.lang.Float;
import java.lang.Math;

public class Nan {
    public static void main(String[] args) {
        // Generate some NaNs.
        float nan            = Float.NaN;
        float zero_div_zero  = 0.0f / 0.0f;
        float sqrt_negative  = (float)Math.sqrt(-1.0);
        float log_negative   = (float)Math.log(-1.0);
        float inf_minus_inf  = Float.POSITIVE_INFINITY - Float.POSITIVE_INFINITY;
        float inf_times_zero = Float.POSITIVE_INFINITY * 0.0f;
        float quiet_nan1     = Float.intBitsToFloat(0x7fc00001);
        float quiet_nan2     = Float.intBitsToFloat(0x7fc00002);
        float signaling_nan1 = Float.intBitsToFloat(0x7fa00001);
        float signaling_nan2 = Float.intBitsToFloat(0x7fa00002);
        float nan_minus      = -nan;

        // Generate some infinities.
        float positive_inf   = Float.POSITIVE_INFINITY;
        float negative_inf   = Float.NEGATIVE_INFINITY;
        float one_div_zero   = 1.0f / 0.0f;
        float log_zero       = (float)Math.log(0.0);

        // Double check that they are actually NaNs.
        assert  Float.isNaN(nan);
        assert  Float.isNaN(zero_div_zero);
        assert  Float.isNaN(sqrt_negative);
        assert  Float.isNaN(inf_minus_inf);
        assert  Float.isNaN(inf_times_zero);
        assert  Float.isNaN(quiet_nan1);
        assert  Float.isNaN(quiet_nan2);
        assert  Float.isNaN(signaling_nan1);
        assert  Float.isNaN(signaling_nan2);
        assert  Float.isNaN(nan_minus);
        assert  Float.isNaN(log_negative);

        // Double check that they are infinities.
        assert  Float.isInfinite(positive_inf);
        assert  Float.isInfinite(negative_inf);
        assert !Float.isNaN(positive_inf);
        assert !Float.isNaN(negative_inf);
        assert one_div_zero == positive_inf;
        assert log_zero == negative_inf;
            // Double check infinities.

        // See what they look like.
        System.out.printf("nan            0x%08x %f\n", Float.floatToRawIntBits(nan           ), nan           );
        System.out.printf("zero_div_zero  0x%08x %f\n", Float.floatToRawIntBits(zero_div_zero ), zero_div_zero );
        System.out.printf("sqrt_negative  0x%08x %f\n", Float.floatToRawIntBits(sqrt_negative ), sqrt_negative );
        System.out.printf("log_negative   0x%08x %f\n", Float.floatToRawIntBits(log_negative  ), log_negative  );
        System.out.printf("inf_minus_inf  0x%08x %f\n", Float.floatToRawIntBits(inf_minus_inf ), inf_minus_inf );
        System.out.printf("inf_times_zero 0x%08x %f\n", Float.floatToRawIntBits(inf_times_zero), inf_times_zero);
        System.out.printf("quiet_nan1     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan1    ), quiet_nan1    );
        System.out.printf("quiet_nan2     0x%08x %f\n", Float.floatToRawIntBits(quiet_nan2    ), quiet_nan2    );
        System.out.printf("signaling_nan1 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan1), signaling_nan1);
        System.out.printf("signaling_nan2 0x%08x %f\n", Float.floatToRawIntBits(signaling_nan2), signaling_nan2);
        System.out.printf("nan_minus      0x%08x %f\n", Float.floatToRawIntBits(nan_minus     ), nan_minus     );
        System.out.printf("positive_inf   0x%08x %f\n", Float.floatToRawIntBits(positive_inf  ), positive_inf  );
        System.out.printf("negative_inf   0x%08x %f\n", Float.floatToRawIntBits(negative_inf  ), negative_inf  );
        System.out.printf("one_div_zero   0x%08x %f\n", Float.floatToRawIntBits(one_div_zero  ), one_div_zero  );
        System.out.printf("log_zero       0x%08x %f\n", Float.floatToRawIntBits(log_zero      ), log_zero      );

        // NaN comparisons always fail.
        // Therefore, all tests that we will do afterwards will be just isNaN.
        assert !(1.0f < nan);
        assert !(1.0f == nan);
        assert !(1.0f > nan);
        assert !(nan == nan);

        // NaN propagate through most operations.
        assert Float.isNaN(nan + 1.0f);
        assert Float.isNaN(1.0f + nan);
        assert Float.isNaN(nan + nan);
        assert Float.isNaN(nan / 1.0f);
        assert Float.isNaN(1.0f / nan);
        assert Float.isNaN((float)Math.sqrt((double)nan));
    }
}

输出:

javac Nan.java && java -ea Nan

因此,我们从中学到了一些东西:

    没有任何明智结果的
  • 奇怪的浮动操作会给出NaN:

    • nan 0x7fc00000 NaN zero_div_zero 0x7fc00000 NaN sqrt_negative 0xffc00000 NaN log_negative 0xffc00000 NaN inf_minus_inf 0x7fc00000 NaN inf_times_zero 0x7fc00000 NaN quiet_nan1 0x7fc00001 NaN quiet_nan2 0x7fc00002 NaN signaling_nan1 0x7fa00001 NaN signaling_nan2 0x7fa00002 NaN nan_minus 0xffc00000 NaN positive_inf 0x7f800000 Infinity negative_inf 0xff800000 -Infinity one_div_zero 0x7f800000 Infinity log_zero 0xff800000 -Infinity
    • 0.0f / 0.0f
    • sqrt(-1.0f)

    生成log(-1.0f)

    在C语言中,实际上可以使用NaN请求在此类操作上引发信号以检测到它们,但我认为它不在Java中公开:Why does integer division by zero 1/0 give error but floating point 1/0.0 returns "Inf"?

  • 在正负无穷限制内的怪异运算会给出+-无限而不是NaN

    • feenableexcept
    • 1.0f / 0.0f

    log(0.0f)几乎属于此类,但是可能的问题是它可以达到正无穷大或负无穷大,因此保留为NaN。

  • 如果NaN是浮动操作的输入,则输出也往往是NaN

  • NaN 0.00x7fc000000x7fc00001可能有多个值,尽管x86_64似乎只生成0x7fc00002

  • NaN和无穷大具有相似的二进制表示形式。

    让我们分解其中的一些:

    0x7fc00000

    由此我们确认IEEE754指定了什么:

    • NaN和无穷都具有指数== 255(全都是)
    • 无限式的尾数==0。因此,只有两种可能的无限式:+和-,由符号位来区分
    • NaN的尾数!=0。因此,除了尾数== 0(无穷大)外,还有几种可能性
  • NaN可以是正数或负数(最高位),尽管它对正常操作没有影响

在Ubuntu 18.10 amd64,OpenJDK 1.8.0_191中进行了测试。