1.浮点类型的存储
float存储需求是4字节(32位), 其中1位最高位是符号位,中间8位表示阶位,后32位表示值
double存储需求是8字节(64为),其中1位最高位是符号位,中间11位表示阶位,后52位表示值
如下图所示:
double 表示这种类型的数值精度是 float 类型的两倍(有人称之为双精度数值)。绝大部
分应用程序都采用 double 类型。在很多情况下,float 类型的精度很难满足需求。实际上,只
有很少的情况适合使用 float 类型,例如,需要单精度数据的库, 或者需要存储大量数据。
float 类型的数值有一个后缀 F 或 f (例如, 3.14F)。没有后缀 F 的浮点数值(如 3.14 ) 默
认为 double 类型。当然,也可以在浮点数值后面添加后缀 D 或 d (例如,3.14D)。
2.浮点数类型的精度丢失
public class SimpleTest {
public static void main(String[] args) {
System.out.println(1.2 - 1);
}
}
该代码块输出为
0.19999999999999996
而非预料中的0.2。
产生的原因是二进制表示十进制小数产生的问题
十进制0.2转换为2进制的过程为:
0.2 * 2 = 0.4 取整数部分 0
0.4 * 2 = 0.8 取整数部分 0
0.8 * 2 = 1.6 取整数部分 1
0.6 * 2 = 1.2 取整数部分 1
0.2 * 2 = 0.4 取整数部分 0
……
过程是一个无限循环。
0.2的2进制从上到下可以表示为 00110011......,小数的二进制表示有时是不可能精确的,正如十进制小数无法准确表示1/3,二进制也无法准确表示1/5。
精度丢失就是我们有限的存储位置无法容纳有时无限的二进制小数。
3.精度丢失的解决
浮点数值不适用于无法接受舍入误差的金融计算中。 例如,命令 System.out.println
( 2.0-1.1 ) 将打印出 0.8999999999999999, 而不是人们想象的 0.9。这种舍入误差的主要
原因是浮点数值采用二进制系统表示, 而在二进制系统中无法精确地表示分数 1/10。 这
就好像十进制无法精确地表示分数 1/3
就应该使用 BigDecimal类。
代码演示:
public static void main(String[] args) {
BigDecimal b1 = new BigDecimal(Float.toString(1.2f));
BigDecimal b2 = new BigDecimal(Float.toString(1));
float s = b1.subtract(b2).floatValue();
System.out.println("s----" + s);
}