Java 四舍五入误差
在编写代码时,我们经常犯各种错误,例如溢出错误和语法错误。四舍五入误差是一种常见错误,可能导致给定的数学问题的错误解。通常,当我们使用浮点数时会出现这种错误。
在本文中,我们将探讨这个问题的原因,并尝试找到一种摆脱这种错误的方法。
四舍五入错误
浮点类型
它们也称为实数,在计算需要分数值时使用。它表示具有小数点的数字。例如,表示1/5的结果即0.2,正弦和余弦的结果也需要小数点。
在Java中,有两种浮点数类型:
- Float - 它可以存储最多32位的单精度值。我们使用’float’关键字声明。
-
Double - 它的大小相对于float更大,可以存储最大64位的双精度值。它使用’double’关键字声明。
让我们讨论一个示例,在这个示例中我们可能会遇到四舍五入误差,然后我们将理解原因并提供正确处理它的解决方案。
示例1
public class Main{
public static void main(String[] args) {
double data1 = 0.30;
double data2 = 0.20 + 0.10;
System.out.println("Value after addition: " + data2);
System.out.println(data1 == data2);
double data3 = 0.50;
double data4 = 0.10 + 0.10 + 0.10 + 0.10 + 0.10;
System.out.println("Value after addition: " + data4);
System.out.println(data3 == data4);
}
}
输出
Value after addition: 0.30000000000000004
false
Value after addition: 0.5
true
在上面的代码中,我们在第一次相加时,‘data2’的预期值是0.30,但输出的结果是错误的。但是,当我们进行另一个类似的相加操作时,我们得到了准确的结果。 让我们看另一个展示错误的示例。
示例2
public class Main {
public static void main(String[] args) {
double data1 = 4.30452;
double data2 = 0.503542;
double res = data1 + data2;
System.out.println("Value after addition: " + res);
}
}
输出
Value after addition: 4.8080620000000005
预期输出为4.808062,但是我们这里得到了错误的输出。
错误原因
‘IEEE 754’是Java在实现浮点数时遵循的标准。根据其“舍入”规则,当尾数的值大于23位时,它会在第23位上添加1来舍入值。这里,尾数是小数点后面的二进制表示。
这就是为什么我们得到不同的值的原因。
错误的解决方法
为了避免这个舍入错误,我们有以下几种方法 –
- BigDecimal - 它是一个可以用来代替浮点数(如float和double)的类。我们可以执行所有浮点数和双精度数据类型提供的常规操作,比如算术运算、比较和舍入。它可以以精确的精度处理这些操作。
以下示例演示了如何使用它来产生准确的结果。
示例3
import java.math.*;
public class Main{
public static void main(String[] args) {
BigDecimal data1 = new BigDecimal("0.20");
BigDecimal data2 = new BigDecimal("0.10");
BigDecimal res = data1.add(data2); // performing addition
System.out.println("Value after addition: " + res);
}
}
输出
Value after addition: 0.30
在示例1中,我们在添加两个值时出现错误。在上面的示例中,我们使用相同的值,但这次我们得到了正确的结果。
- Math.round() −这是一个静态方法,属于‘Math’类。它接受一个浮点值作为参数,并返回最接近的整数值。我们使用它的类名调用它。
下面的示例说明了它在程序中的使用。
示例4
public class Main {
public static void main(String[] args) {
double data1 = 4.30452;
double data2 = 0.503542;
double res = data1 + data2;
System.out.println("Value after addition: " + res);
System.out.println("Value after rounding off the addition: " + Math.round(res));
}
}
输出
Value after addition: 4.8080620000000005
Value after rounding off the addition: 5
结论
舍入误差不是编译时错误或运行时错误,Java编译器无法检测到它。这就是为什么程序员需要额外注意这些错误,否则我们将得到错误的结果。在本文中,我们讨论了原因,并提出了一些克服这种舍入误差的方法。