java中的NaN和Infinity

今天,我朋友给我问了一个问题:怎么快速判断一个 double 数是否在另外两个 double 数之间?(说这是个面试题)
进而就找到了NaN和Infinity。
java浮点数运算中有两个特殊的情况:NaN、Infinity。

一、Infinity(中文是无穷大的意思)

在浮点数运算时,有时我们会遇到除数为0的情况,那java是如何解决的呢?
我们知道,在整型运算中,除数是不能为0的,否则直接运行异常。但是在浮点数运算中,引入了无限这个概念,我们来看一下Double和Float中的定义。
浮点数中的包装类是这么定义Infinity的:

Float包装类中是这么定义的:
首先要看一下Float包装类继承实现了哪些类?

public final class Float extends Number implements Comparable {}

1、正无穷大:Infinity

  public static final float POSITIVE_INFINITY = 1.0f / 0.0f;

2、负无穷大:-Infinity

    public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;

Double包装类中是这么定义的:
首先要看一下Double包装类继承实现了哪些类?

public final class Double extends Number implements Comparable {}

1、正无穷大:Infinity

public static final double POSITIVE_INFINITY = 1.0 / 0.0;

2、负无穷大:-Infinity

 public static final double NEGATIVE_INFINITY = -1.0 / 0.0;

那么这些值对运算会有什么影响呢?

System.out.println(Double.POSITIVE_INFINITY);// Infinity
System.out.println(Double.NEGATIVE_INFINITY);// -Infinity

我们先思考一下下面几个问题:

1.无限乘以0会是什么?
2.无限除以0会是什么?
3.无限除以无限会是什么?
4.无限做除了1、2、3外的运算结果是什么?
探索:

  1. 无限乘以0,结果为NaN
System.out.println(Float.POSITIVE_INFINITY * 0); // output: NaN
System.out.println(Float.NEGATIVE_INFINITY * 0); // output: NaN

2.无限除以0,结果不变,还是无限

System.out.println(Float.POSITIVE_INFINITY / 0); // output:Infinity
System.out.println(Float.NEGATIVE_INFINITY / 0 ); // output: -Infinity
        
System.out.println((Float.POSITIVE_INFINITY / 0) == Float.POSITIVE_INFINITY); // output: true
System.out.println((Float.NEGATIVE_INFINITY / 0) == Float.NEGATIVE_INFINITY); // output: true

3.无限除以无限,结果为NaN

System.out.println(Double.POSITIVE_INFINITY / Double.POSITIVE_INFINITY);// NaN
System.out.println(Double.POSITIVE_INFINITY / Double.NEGATIVE_INFINITY);// NaN
System.out.println(Double.NEGATIVE_INFINITY / Double.NEGATIVE_INFINITY);// NaN

4.无限做除了乘以0和除以无限以外的运算,结果还是无限

System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY + 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY - 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY * 10000)); // output: true
System.out.println(Float.POSITIVE_INFINITY == (Float.POSITIVE_INFINITY / 10000)); // output: true

要判断一个浮点数是否为INFINITY,可用isInfinite方法:

System.out.println(Double.isInfinite(Float.POSITIVE_INFINITY)); // output: true

其源码如下:

 public static boolean isInfinite(double v) {
        return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
    }

总结:

无限乘以0=NaN
无限除以无限=NaN
除了这两个操作,其他操作无限的结果都是无限

来看一个小例子:
i == i + 1;这个一般来说是返回false吧,一个数字永远不会等于它自己加1,这是正常的思维,但是我们知道无穷大加一还是无穷大。这也验证了上述的小总结。
事实上,你不必将i 初始化为无穷大以确保返回true。任何足够大的浮点数都可以实现这一目的,例如:

double i = 1.0e40;
System.out.println(i == i + 1);// true

二、NaN(Not a number)

Java中NaN是这么定义的:

 public static final float NaN = 0.0f / 0.0f;
 public static final double NaN = 0.0d / 0.0;

NaN表示非数字,它与任何值都不相等,甚至不等于它自己,所以要判断一个数是否为NAN要用isNAN方法:
这个方法源码是这样的:

 public static boolean isNaN(double v) {
        return (v != v);
    }
System.out.println(Float.NaN == Float.NaN); // output: false
System.out.println(Double.isNaN(Float.NaN)); // output: true
System.out.println(Double.NaN != Double.NaN);// output: true

总结:

NaN表示非数字,它与任何值都不相等,甚至不等于自己;
NaN与任何数比较均返回false;
任何浮点操作,只要它的一个或多个操作数为NaN,那么其结果为NaN。

来看一个小例子:
i != i ;一个数字总是等于它自己,一般正常的思维肯定是这样的。但是,浮点算术保留了一个特殊的值用来表示一个不是数字的数量,这个值就是NaN(“不是一个数字(Not a Number)”的缩写),对于所有没有良好的数字定义的浮点计算,例如0.0/0.0,其值都是它。规范中描述道,NaN 不等于任何浮点数值,包括它自身在内。NaN 还有其他的惊人之处。任何浮点操作,只要它的一个或多个操作数为NaN,那么其结果为NaN。

NaN表示非数字,它与任何值都不相等,甚至不等于自己:

System.out.println(Double.NaN == Double.NaN);// false
Double a = new Double(Double.NaN);
Double b = new Double(Double.NaN);
System.out.println(a.equals(b)); // true
System.out.println(Double.NaN != Double.NaN);// true

NaN与任何数比较均返回false:

double c = Double.NaN;
        if ((0 > c) || (0 == c) || (0 < c)) {
            System.out.println("NaN compared with 0 is not always false.");
        } else {
            //执行这个
            System.out.println("NaN compared with 0 is always false!");
        }

最后,我们来看一下这个面试题:
既然我们知道浮点数中有NaN这个数,那么我们在比较前要不要判断下这个数是不是NaN呢,利用包装类中的isNaN方法判断。继而再比较。

2018、05、03

你可能感兴趣的:(java中的NaN和Infinity)