float、double、decimal数据类型及区别应用

三里河河之光刘润煦
作者:admin来源:编写 日期:2021/5/15 7:21:29浏览次数:

这里讲述float、double、decimal数据类型及区别应用

当用float、double浮点型数据处理具有一定精度要求的数据时,如货币交易等,通常会出现一些奇怪的现象。举个例子:

System.out.println( 1f == 0.9999999f );   // 打印:false

System.out.println( 1f == 0.99999999f );  // 打印:true 

上例是判断两个浮点型是否相等(1和0.9999999、1和0.99999999)一个7位小数点、一个8位小数点。

判断的结果:第一个为false,第二个为true。为什么会出现这样的结果呢,这要从浮点数的计算机底层存储原理说起。我们通常所理解的十进制数,计算机底层在计算时并不是按照十进制来计算的,学过基本计算机原理的都知道,计算机底层最终都是基于像010100100100110011011这种0、1二进制来完成的。

我们要将上面两个十进制的浮点数转化为机器所识别的二进制看一看:

1f(十进制)

    ↓

00111111 10000000 00000000 00000000(二进制)

0.9999999f(十进制)

    ↓

00111111 01111111 11111111 11111110(二进制)

0.99999999f(十进制)

    ↓

00111111 10000000 00000000 00000000(二进制)

由此可见,二进制表示下的1f与0.99999999f是一样的,所以返回true。另外一种返回false。

为什么0.99999999f的二进制表示会跟1f的一样?这要谈一下浮点数的精度问题。

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位。

对应上面的数值0.99999999f,很明显已经超出了float类型的精度范围,所以出现问题是难免的。

float和double是浮点二进制点类型。他代表这样一个数字:10001.10010110011。

decimal是浮点小数点类型。他代表这样一个数字:12345.65789。decimal小数点的位置和数字都被编码在值中,这就是decimal仍然是浮点类型而不是固定点类型的原因。

人们习惯用十进制形式表示非整数,并期望十进制表示中的确切结果,并非所有的十进制数都可以在二进制浮点数中精确表示,例如0.1,所以如果使用二进制浮点数值,则实际上会得到0.1的近似值。|#|#|

float、double、decimal精度是主要区别,各自的精度如下:

float浮动-7位数字(32位)

double双-15-16位(64位)

decimal十进制-28-29有效数字(128位)

十进制结构严格适用于要求精确度的财务计算,具有金融价值的例子,这些计算相对不能四舍五入,使用decimal是很好的。尽管支持更多数字的精度,但十进制的值范围小于双精度值。 因此,十进制不能用来表示许多科学价值。

对于自然界更多的人为因素,无论如何都无法准确测量,float/double更合适。例如,科学数据通常以这种形式表示。在许多科学计算中,某些精确度的损失是可以接受的,因为要测量的物理问题或伪影的实际限制。 精确度的损失在财务上是不可接受的。

在运算速度方面:对于大多数操作来说,浮点二进制点类型比小数点处理速度快得多。十进制比浮点和双精度慢得多。这也是decimal和float、double类型的一个重要运算区别。

 

欢迎阅读、分享,转载和使用请注明出处,文章来自三里河之光-风、物、情

也可承接私活网站建设、小程序,项目实优,联系qq:38623483。项目交流群:315939322。

 

中华人民共和国