浮点数在内存中的表现形式, Infinity和NaN的出现情况及特点(通俗解释)
(本着通俗易懂来解释,其中很多概念并没有说到,如有错误,欢迎指正,感谢!)
首先看代码
public static void main(String[] args) {
// System.out.println(12%0); / by zero
System.out.println(10 % 0.0); // NaN
System.out.println(1.2 % 0); // NaN
System.out.println(1.2 % 0.0); // NaN
System.out.println("============================");
// System.out.println(12 / 0); / by zero
System.out.println(1.2 / 0.0); // Infinity
System.out.println(1.2 / 0); // Infinity
System.out.println(1.2 / 0.0); // Infinity
}
为什么这些浮点数运算中,操作数为含有0时,并没有抛出异常,而是打印出Infinity与 NaN, 这两个又是什么?
- 查看Java源码
1. Float中
public static final float POSITIVE_INFINITY = 1.0F / 0.0; //正无穷大
public static final float NEGATIVE_INFINITY = -1.0F / 0.0; //负无穷大
public static final float NaN = 0.0F / 0.0; //非数
2.Double中
public static final double POSITIVE_INFINITY = 1.0D / 0.0; //正无穷大
public static final double NEGATIVE_INFINITY = -1.0D / 0.0; //正无穷小
public static final double NaN = 0.0D / 0.0; //非数
其中确实定义了Infinity与NaN
浮点数在计算机中内部的表现形式
数字是无限的,内存空间是有限的
- 浮点数在计算机中遵循IEEE 754标准
计算机内部是无法精确表示浮点数的。
System.out.printf("%.17f",(0.1+0.2)); // 输出: 0.30000000000000004
根据标准,浮点数在计算机内部存储原理:
以float(32位)为例
符号位区域 | 指数位区域 | 小数位区域 |
---|---|---|
1位 | 8位 | 23位 |
- 浮点数在计算机内部中的表示,被分为三个区域:
符号位区域(31),指数位区域(30-23),小数位区域(22-0)
- 指数区域的数值是偏移过的数值 = “真正的指数位 + 偏移量” 的编码方式
- 偏移量是为了表达负数设计的
- float类型的偏移量默认为127
内部二进制转换成原始浮点数公式
实际数字 = (-1)符号位值 × 2指数位值-127 × 1.小数位值
假设浮点数是: 3.14
对应的二进制为:11.00100011110101110000000(也许有效位过长后面还有,但小数位只有23位,到这里结束,将之后的舍入,舍入也有对应的规则)
换算成科学计数法为: 1.10010001111010111000000 × 2 1
真正的指数为:1
偏移过的指数为:1+127=128 真指数经过偏移值进行偏移
正数,符号位区域为:1
偏移过的指数在指数位区域表示: 10000000
尾数区域表示: 10010001111010111000000
所以整个表示为: 0 10000000 10010001111010111000000
通过上述公式,可以将二进制数还原
运算过程结果为:
(−1)0×10(10000000 − 01111111)×1.10010001110101110000000
= 1×21×1.5696868896484375
= 3.139373779296875
与3.14相比很明显出现偏差
IEEE 754标准中规定
- 如果指数位区域全为1(255),且小数位为0(0),根据符号位表示正无穷大或负无穷大(+/- Infinity)
- 当0.0作为为除数 或者 浮点数除0就会出现这种情况
- 如果指数位区域全位1,且小数位不为0,这个数表示为不是一个数(NaN)
- 取余运算中0.0作为后者 或者 浮点数%0时会出现该情况
浮点数表现形式参考网址: 浮点数表现形式
Infinity特点
- 无限乘以0=NaN
- 无限除以无限=NaN
- 除了这两个操作,其它对无限的操作结果都是无限
NaN特点:
- NaN表示非数(不是数),包括它自身在内。
- 任何没有良好定义浮点运算,结果都为NaN
- 对负数求平方根,结果为NaN
- 任何运算中只要含有NaN,则结果为NaN
- NaN用在关系表达式中,整个表达式结果为false
更多详解:
百度百科–IEE 754
https://zhuanlan.zhihu.com/p/89320102
参考资料:
https://zhuanlan.zhihu.com/p/89320102
( 注:部分资料参考网络,如有侵权请联系。)