在Java中,NaN是什么意思?

发布于 2024-08-28 15:17:02 字数 98 浏览 9 评论 0原文

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

Java 中 NaN 是什么意思?

I have a program that tries to shrink a double down to a desired number. The output I get is NaN.

What does NaN mean in Java?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

北城孤痞 2024-09-04 15:17:02

摘自此页面

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

Taken from this page:

"NaN" stands for "not a number". "Nan"
is produced if a floating point
operation has some input parameters
that cause the operation to produce
some undefined result. For example,
0.0 divided by 0.0 is arithmetically undefined. Taking the square root of a
negative number is also undefined.

毁虫ゝ 2024-09-04 15:17:02

NaN 表示“不是数字”,基本上是 IEE 754 浮点 标准。 NaN 通常表示该值无法用有效的浮点数表示。

当要转换的值是其他值时(例如转换不代表数字的字符串时),转换将产生此值。

NaN means “Not a Number” and is basically a representation of a special floating point value in the IEE 754 floating point standard. NaN generally means that the value is something that cannot be expressed with a valid floating point number.

A conversion will result in this value, when the value being converted is something else, for example when converting a string that does not represent a number.

悍妇囚夫 2024-09-04 15:17:02

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

NaN means "Not a Number" and is the result of undefined operations on floating point numbers like for example dividing zero by zero. (Note that while dividing a non-zero number by zero is also usually undefined in mathematics, it does not result in NaN but in positive or negative infinity).

折戟 2024-09-04 15:17:02

最小可运行示例

您必须了解的第一件事是 NaN 的概念是直接在 CPU 硬件上实现的。

所有主要的现代 CPU 似乎都遵循 IEEE 754,它指定了浮点格式和 NaN,它们只是特殊的浮点值是该标准的一部分。

因此,这个概念在任何语言中都非常相似,包括 Java,它只是直接向 CPU 发出浮点代码。

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

现在进行一些 Java 操作。大多数不在核心语言中的感兴趣的函数都位于 java.lang.Float

Nan.java

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));
    }
}

GitHub 上游

运行:

javac Nan.java && java -ea 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

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

  • 奇怪的浮点运算没有任何合理的结果,给出 NaN:

    • 0.0f / 0.0f
    • sqrt(-1.0f)
    • 日志(-1.0f)

    生成一个NaN

    在 C 中,实际上可以使用 feenableexcept 请求在此类操作上引发信号来检测它们,但我不认为它在 Java 中公开:为什么整数除以零 1/0 会出错,但浮点 1/0.0 返回“Inf”?

  • 在正或负无穷大的极限上的奇怪运算,但确实给出 +- 无穷大而不是 NaN

    p>

    • 1.0f / 0.0f
    • 日志(0.0f)

    0.0 几乎属于这一类,但问题可能是它可能会达到正无穷大或负无穷大,因此它被保留为 NaN。

  • 如果 NaN 是浮点运算的输入,输出也趋向于 NaN

  • 有几个可能的值NaN 0x7fc000000x7fc000010x7fc00002,尽管 x86_64 似乎只生成 0x7fc00000

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

    让我们分解其中的一些:

    <预><代码>nan = 0x7fc00000 = 0 11111111 10000000000000000000000
    正_inf = 0x7f800000 = 0 11111111 00000000000000000000000
    负数inf = 0xff800000 = 1 11111111 00000000000000000000000
    | | |
    | |尾数
    |指数
    |
    符号

    由此我们确认 IEEE754 的规定:

    • NaN 和无穷大的指数 == 255(全数)
    • 无穷大的尾数 == 0。因此只有两种可能的无穷大:+ 和 -,通过符号位区分
    • NaN 的尾数 != 0。因此,有多种可能性,但尾数 == 0 除外,它是无穷大
  • NaN 可以是正数或负数(最高位),尽管这对正常操作没有影响< /p>

在 Ubuntu 18.10 amd64、OpenJDK 1.8.0_191 中测试。

Minimal runnable example

The first thing that you have to know, is that the concept of NaN is implemented directly on the CPU hardware.

All major modern CPUs seem to follow IEEE 754 which specifies floating point formats, and NaNs, which are just special float values, are part of that standard.

Therefore, the concept will be the very similar across any language, including Java which just emits floating point code directly to the CPU.

Before proceeding, you might want to first read up the following answers I've written:

Now for some Java action. Most of the functions of interest that are not in the core language live inside java.lang.Float.

Nan.java

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));
    }
}

GitHub upstream.

Run with:

javac Nan.java && java -ea Nan

Output:

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

So from this we learn a few things:

  • weird floating operations that don't have any sensible result give NaN:

    • 0.0f / 0.0f
    • sqrt(-1.0f)
    • log(-1.0f)

    generate a NaN.

    In C, it is actually possible to request signals to be raised on such operations with feenableexcept to detect them, but I don't think it is exposed in Java: Why does integer division by zero 1/0 give error but floating point 1/0.0 returns "Inf"?

  • weird operations that are on the limit of either plus or minus infinity however do give +- infinity instead of NaN

    • 1.0f / 0.0f
    • log(0.0f)

    0.0 almost falls in this category, but likely the problem is that it could either go to plus or minus infinity, so it was left as NaN.

  • if NaN is the input of a floating operation, the output also tends to be NaN

  • there are several possible values for NaN 0x7fc00000, 0x7fc00001, 0x7fc00002, although x86_64 seems to generate only 0x7fc00000.

  • NaN and infinity have similar binary representation.

    Let's break down a few of them:

    nan          = 0x7fc00000 = 0 11111111 10000000000000000000000
    positive_inf = 0x7f800000 = 0 11111111 00000000000000000000000
    negative_inf = 0xff800000 = 1 11111111 00000000000000000000000
                                | |        |
                                | |        mantissa
                                | exponent
                                |
                                sign
    

    From this we confirm what IEEE754 specifies:

    • both NaN and infinities have exponent == 255 (all ones)
    • infinities have mantissa == 0. There are therefore only two possible infinities: + and -, differentiated by the sign bit
    • NaN has mantissa != 0. There are therefore several possibilities, except for mantissa == 0 which is infinity
  • NaNs can be either positive or negative (top bit), although it this has no effect on normal operations

Tested in Ubuntu 18.10 amd64, OpenJDK 1.8.0_191.

鹿童谣 2024-09-04 15:17:02

NaN 表示“不是数字”。它是一个特殊的浮点值,意味着运算结果未定义或无法表示为实数。

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

NaN means "Not a number." It's a special floating point value that means that the result of an operation was not defined or not representable as a real number.

See here for more explanation of this value.

月下凄凉 2024-09-04 15:17:02

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

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

NaN stands for Not a Number. It is used to signify any value that is mathematically undefined. Like dividing 0.0 by 0.0.
You can look here for more information: https://web.archive.org/web/20120819091816/http://www.concentric.net/~ttwang/tech/javafloat.htm

Post your program here if you need more help.

御弟哥哥 2024-09-04 15:17:02

NaN = 不是数字。

NaN = Not a Number.

吝吻 2024-09-04 15:17:02

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

Means Not a Number.
It is a common representation for an impossible numeric value in many programming languages.

顾北清歌寒 2024-09-04 15:17:02

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

Not a Java guy, but in JS and other languages I use it's "Not a Number", meaning some operation caused it to become not a valid number.

や莫失莫忘 2024-09-04 15:17:02

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

查看此参考中的“Not A Number”部分

It literally means "Not a Number." I suspect something is wrong with your conversion process.

Check out the Not A Number section at this reference

梦亿 2024-09-04 15:17:02

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

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

Not a valid floating-point value (e.g. the result of division by zero)

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文