关于java浮点数运算精度丢失问题的
首先我们需要知道机器数和真值的概念,一个数在计算机中以二进制形式表示就是该数对应的机器数,而且机器数是带符号的,最高位就是符号位,0代表正数,代表负数。因为机器数带符号位,所以机器数的形式值不是真正的数值,我们将带符号位的机器数对应的真正数值称为机器数的真值。
因此数字在计算机都是以二进制形式存储的,接下来我们就可以介绍原码,反码,补码,它们是机器存储一个具体数字的编码方式,原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值,原码是人脑最容易理解和计算的表示方式;反码的表示方法是:正数的反码是其本身;负数的反码是在其原码的基础上,符号位不变,其余各位取反。如果一个反码表示的是负数,人脑无法直观的看出来它的数值。通常要将其转换成原码再计算。补码的表示方法是:正数的补码就是其本身;负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1。(也即在反码的基础上+1)。对于负数而言和反码一样,也许转换成原码进行计算。之后我们发现三者的关系,对于原码来说,它只有加法,而没有减法,为了解决减法问题,于是我们创造了反码,减去一个数可以看成加一个数的负数,这样负数相加的问题就解决了,而且正数的原码等于本身,是因为正数之间的加法需要原码,而减法需要反码,之后我们发现了一个棘手的盲点,那就是0的表示如果用原码或者反码都有两种方式10000,00000,-0和+0,为了解决这个问题我们提出了补码的概念,这样所有的问题就得以解决了,这样0只剩一种表示方式,正数原码反码补码都一样,而负数反码等于正数取反,而补码为反码结尾补1。
在java语言中进行浮点数运算时我们会发现精度损失的情况,计算机的 CPU 表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。在浮点数运算的过程当中这是必然的,那么如何解决呢?其实 Java 的浮点数只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal 类来进行精确计算。
- 用 float 或者 double 变量构建 BigDecimal 对象。通常使用 BigDecimal 的构造方法或者静态方法的 valueOf() 方法把基本类型的变量构建成 BigDecimal 对象。
- 通过调用 BigDecimal 的加,减,乘,除等相应的方法进行算术运算。
- 把 Bi
- gDecimal 对象转换成 float,double,int 等类型
BigDecimal add(BigDecimal augend) //加法运算
BigDecimal subtract(BigDecimal subtrahend) //减法运算
BigDecimal multiply(BigDecimal multiplicand) //乘法运算
BigDecimal divide(BigDecimal divisor) //除法运算
这样就解决了精度丢失的问题