很多人都知道Java中的浮点数是不准确的,需要使用BigDecimal来进行准确的计算。然而,很少有人知道为什么浮点数不准确?为什么使用不准确的数字?本文将分析wave。我们知道计算机数字的存储和运算都是通过二进制进行的。十进制整数转化为二进制整数,采用“除以2余数取余倒序”的方法,具体方法是:将十进制整数除以2得商和余数;然后用2除商,得到商和余数,依次进行,直到商小于1,然后将先得到的余数作为二进制数的低位有效位,得到的余数后面作为二进制数的高位有效位依次排列,比如我们要将127转成二进制,如下:十进制小数化为二进制小数采用“乘以2取整,并顺序排列”的方法。具体方法是:小数乘以2,可以得到乘积,取出乘积的整数部分,再将剩余的小数部分乘以2,得到另一个乘积,再取出乘积的整数部分,依此类推,直到乘积中的小数部分为零,此时二进制的最后一位为0或1。或者直到达到要求的精度。比如尝试把0.625转换成二进制:但是0.625是一个特殊的列,用同样的算法,请计算0.1对应的二进制数是多少:我们发现0.1的二进制表示存在一个死循环,即,(0.1)10=(0.000110011001100…)2在这种情况下,计算机无法用二进制准确表示0.1。因此,为了解决一些小数不能用二进制准确表示的问题,就有了IEEE754规范。IEEE二进制浮点运算标准(IEEE754)是自1980年代以来使用最广泛的浮点运算标准。它由浮点运算符使用。浮点数和小数并不完全相同。小数在计算机中的表示实际上有两种:定点数和浮点数。因为在位数相同的情况下,定点数的表示范围比浮点数小。所以在计算机科学中,浮点数被用来表示实数的近似值。IEEE754规定了四种表示浮点值的方式:单精度(32位)、双精度(64位)、扩展单精度(超过43位,很少使用)和扩展双精度(超过79位,通常实现80位)。最常用的是32位单精度浮点数和64位双精度浮点数。单精度浮点数在计算机内存中占用4个字节(32位)。使用“浮点数”(浮动小数点)的方法,可以表示很大范围的数值。与单精度浮点数相比,双精度浮点数(double)使用64位(8字节)来存储一个浮点数。IEEE并没有解决小数不能精确表示的问题,只是提出了一种用近似值表示小数的方法,并引入了精度的概念。浮点数a由两个数m和e表示:a=m×b^e。在任何这样的系统中,我们选择基数b(编号系统的基数)和精度p(即用于存储的位数)。m(即尾数)是一个p位数字,形式为±d.ddd...ddd(每一位是0到b-1之间的整数,包括0和b-1)。如果m的第一位是非零整数,则称m已归一化。有描述使用单个符号位(s代表+或-)来表示符号,所以m必须是正数。e是指数。最后,由于计算机中存储的小数实际上是小数的近似值,而不是精确值,所以不要在代码中使用浮点数来表示金钱等重要指标。建议使用BigDecimal或Long(以分为单位)来表示金额。
