float和double
float和double浮点数类型的精度和范围解析 浮点数类型float和double是编程语言中最常用的数值类型,但是它们的精度和范围却是程序员需要注意的重要问题。本文将详细解释float和double的范围和精度,及其在商业计算中的应用问题和解决方法。 1. 范围 float和double的范围是由指数的位数来决定的。float的指数位有8位,而double的指数位有11位。因此,float的指数范围为-127~+128,而double的指数范围为-1023~+1024。指数位是按补码的形式来划分的,其中负指数决定了浮点数所能表达的绝对值最小的非零数,而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;double的范围为-2^1024 ~+2^1024,也即-1.79E+308 ~ +1.79E+308。 2. 精度 float和double的精度是由尾数的位数来决定的。浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。float的精度为6~7位有效数字,而double的精度为15~16位有效数字。 3. 精度问题 在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。在商业计算中,这种问题尤其严重。如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。 4. 解决方案 四舍五入我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数,我们只能象这样(保留两位):public double round(double value){ return Math.round(value*100)/100.0;}但是,这个方法并不能正常工作,给这个方法传入4.015,它将返回4.01而不是4.02,如我们在上面看到的。java.text.DecimalFormat也不能解决这个问题。 System.out.println(new java.text.DecimalFormat("0.00").format(4.025));输出是4.02。 解决这个问题的方法是使用java.math.BigDecimal。BigDecimal有四个构造方法,其中两个使用 BigInteger,我们不关心;另两个是BigDecimal(double val)和BigDecimal(String val)。这两个方法的API描述相当明确,通常情况下,使用BigDecimal(double val)方法更方便一些。但是,需要注意的是,使用这个方法可能会出现问题,因为double类型的精度问题。例如,new BigDecimal(.1)并不是等于.1,而是等于.1000000000000000055511151231257827021181583404541015625。 因此,在商业计算中,我们应该使用java.math.BigDecimal来避免精度问题,而不是使用float和double类型。