1. 浮点数转换二进制
在进行浮点数转二进制之前,先回顾下整数转二进制如何进行的?
把10进制下123转为2进制,得到1111011(2)
小数转二进制:
10进制下0.71875转为2进制为0.10111
0.71875 * 2 = 1.4375 得到1
0.4375 * 2 = 0.875 得到0
0.875 * 2 = 1.75 得到1
0.75 * 2 = 1.5 得到1
0.5 * 2 = 1.0 得到1
于是得到0.10111
2. 浮点数在计算机中是如何表示的
2.1 IEEE754标准
IEEE754标准提供了浮点数在计算机内存中的存储标准,即以二进制的方式存储十进制浮点数。
浮点数在计算机中的存储方式遵循IEEE 754 浮点数计数标准,可以表示为:
采用尾数 + 阶码的编码方式,更通俗一点说,就是类似于数学课本上所学的科学计数法表示方式:有效数字 + 指数位!
因此,只要给出:符号(S)、阶码部分(E)、尾数部分(M) 这三个维度的信息,一个浮点数的表示就完全确定下来了,所以float和double这两种类型的浮点数在计算机中的存储结构就表示成下图所示这个样子:
- 符号位(s):0-正 1-负
- 阶码部分(E)(指数部分):
对于float型浮点数,指数部分8位,考虑可正可负,因此可以表示的指数范围为-127 ~ 128
对于double型浮点数,指数部分11位,考虑可正可负,因此可以表示的指数范围为-1023 ~ 1024 - 尾数部分(M):
浮点数的精度是由尾数的位数来决定的:
对于float型浮点数,尾数部分23位,换算成十进制就是 2^23=8388608,所以十进制精度只有6 ~ 7位;
对于double型浮点数,尾数部分52位,换算成十进制就是 2^52 = 4503599627370496,所以十进制精度只有15 ~ 16位
2.2 浮点数转换为IEEE754标准示例
float 6.36 = 110.01011100…
1> 转换为IEEE574标准表示: 1.10010111000… x 2^2
2> 对应可得:
- 符号位:0
- 阶码部分:127+2 = 129 = 1000 0001
- 尾数部分:1001011100…,其实它本身无限不循环,但若以float型精度来截取23位,则可以表示为10010111000010100011111
3> 因此最终的总结果为(以32位精度float表示):
01000000110010111000010100011111
3. 浮点数使用注意
先看现象
涉及诸如float或者double这两种浮点型数据的处理时,偶尔总会有一些怪怪的现象,不知道大家注意过没,举几个常见的栗子:
典型现象(一):条件判断超预期
System.out.println( 1f == 0.9999999f ); // 打印:false System.out.println( 1f == 0.99999999f ); // 打印:true 纳尼?
典型现象(二):数据转换超预期
float f = 1.1f; double d = (double) f; System.out.println(f); // 打印:1.1 System.out.println(d); // 打印:1.100000023841858 纳尼?
典型现象(三):基本运算超预期
System.out.println( 0.2 + 0.7 ); // 打印:0.8999999999999999 纳尼?
典型现象(四):数据自增超预期
float f1 = 8455263f; for (int i = 0; i < 10; i++) { System.out.println(f1); f1++; } // 打印:8455263.0 // 打印:8455264.0 // 打印:8455265.0 // 打印:8455266.0 // 打印:8455267.0 // 打印:8455268.0 // 打印:8455269.0 // 打印:8455270.0 // 打印:8455271.0 // 打印:8455272.0 float f2 = 84552631f; for (int i = 0; i < 10; i++) { System.out.println(f2); f2++; } // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗? // 打印:8.4552632E7 纳尼?不是 +1了吗?
看到没,这些简单场景下的使用情况都很难满足我们的需求,所以说用浮点数(包括double和float)处理问题有非常多隐晦的坑在等着咱们!
导致这些的原因都是精度的问题。


