我正在用Java构建一个web应用程序,它可以计算并向用户显示步骤。在用小数做基本算术时,我经常会在准确的输出中感到混乱。
这是我的问题:
double a = 0.15;
double b = 0.01;
System.out.println(a - b);
// outputs 0.13999999999999999
float a = 0.15;
float b = 0.01;
System.out.println(a - b);
// outputs 0.14
float a = 0.16f;
float b = 0.01f;
System.out.println(a - b);
// outputs 0.14999999
double a = 0.16;
double b = 0.01;
System.out.println(a - b);
// outputs 0.15
两者对于complete
的准确性都不可靠。有没有更精确的数字类,或者我应该把值四舍五入?
您可以使用BigDecimal。它很丑陋,但它有效:
BigDecimal a = new BigDecimal("0.15");
BigDecimal b = new BigDecimal("0.01");
System.out.println(a.subtract(b));
请确保使用String参数或valueOf
方法构造它们,如下所示:
BigDecimal x = new BigDecimal("0.15"); // This is ok
BigDecimal x = BigDecimal.valueOf(0.15); // This is also ok
而不是像这样的双参数:
BigDecimal x = new BigDecimal(0.15); // DON'T DO THIS
因为如果传入double,也会将double的不准确性传入新的BigDecimal实例。如果你传入一个字符串,BigDecimal就会知道™做正确的事™.
使用double
时需要应用合理的舍入。如果你这样做,你可以得到15位数的准确度,在大多数情况下这已经足够了。
double a = 0.15;
double b = 0.01;
System.out.printf("%.2f%n", a - b);
double a2 = 0.16;
double b2 = 0.01;
System.out.printf("%.2f%n", a2 - b2);
打印
0.14
0.15
BigDecimal怎么样?
但并不是所有分区都完全准确(例如1/3)。为此,您需要分数,它不是JDK的一部分,但很容易实现,例如作为两个整数(或BigIntegers)。
BigDecimal a = new BigDecimal(".15");
BigDecimal b = new BigDecimal(".01"),
BigDecimal c = new BigDecimal(0);
c = a.subtract(b);
System.out.println(c);