目录

FLOAT和DOUBLE转换

FLOAT和DOUBLE区别

字节

精度

double损失精读的原因:


FLOAT和DOUBLE转换


String str = "9.2";

Long.parseLong(str ); //异常java.lang.NumberFormatException: For input string: "9.2"

Float.parseFloat(str); //可以

Double.parseDouble(str);//可以

System.out.println(2.00-1.10);

输出的结果是:0.8999999999999999


System.out.println(2.00f-1.10f);

输出结果:0.9




System.out.println(2.00-1.10);中的1.10不能被计算机精确存储,以double类型数据1.10举例计算机如何将浮点型数据转换成二进制存储,

这里重点讲小数部分转换成二进制:

1.10整数部分就是1,转换成二进制1(这里整数转二进制不再赘述)

小数部分:0.1


0.1*2=0.2取整数部分0,基数=0.2

0.2*2=0.4取整数部分0,基数=0.4

0.4*2=0.8取整数部分0,基数=0.8

0.8*2=1.6取整数部分1,基数=1.6-1=0.6

0.6*2=1.2取整数部分1,基数=1.2-1=0.2

0.2*2=0.4取整数部分0,基数=0.4



分析:

直至基数为0。1.1用二进制表示为:1.000110...xxxx....(后面表示省略)

0.1 = 0*2^(-1)+0*2^(-2)+0*2^(-3)+1*2^(-4)+.........而double类型表示小数部分只有52位,当向后计算 52位后基数还不为0,那后面的部分只能舍弃,从这里可以看出float、double并不能准确表示每一位小数,对于有的小数只能无限趋向它。


在计算机中加减乘除运算实际上最后都要在计算机中转换成二进制的加运算,由此,当计算机运行System.out.println(2.00-1.10); 时会拿他们在计算机内存中的二进制表示计算,而1.10的二进制表示本身就不准确,所以会出现0.8999999999999999的结果。


解决方法:

使用BigDecimal提供的方法进行比较或运算,但要注意在构造BigDecimal的时候使用float、double的字符串形式构建,BigDecimal(String val);为什么不用BigDecimal(double val)API里写的比较清楚。




FLOAT和DOUBLE区别

字节


float:4个字节

double:8个字节



精度


float精度是:7~8位有效数字

double精度是:16~17位有效数字



double损失精读的原因:

精度损失的原理可以很简单的讲,首先一个正整数在计算机中表示使用01010形式表示的,浮点数也不例外。

正整数除以2肯定会有个尽头的,之后二进制还原成十进制只需要乘以2即可。

  举个例子:0.99用的有效数字部分,

       0.99 * 2 = 1+0.98 --> 1

       0.98 * 2 = 1+0.96 --> 1

       0.96 * 2 = 1+0.92 -- >1

       0.92 * 2 = 1+0.84 -- >1

         ...............

  这样周而复始是没法有尽头的,而double有效数字有限,所以必定会有损失,所以二进制无法准确表示0.99,就像十进制无法准确表示1/3一样。