如何在 Java 中处理精确的精度?

How to deal with exact precision in Java?

提问人:Farhan stands with Palestine 提问时间:12/22/2018 最后编辑:James ZFarhan stands with Palestine 更新时间:12/23/2018 访问量:86

问:

要求是检查位于 2D 平面中的特定点是否穿过特定线。

给出的 2 个首字母点是 和 。 直线的斜率可以计算为(3,1)(12, 3)

(y2-y1) / (x2-x1)

然后可以构造直线方程,其中 m 是斜率,c 是常数。 表示这条线的方程式是y = mx + c2x + 3 = 9y

所以,要检查上面的线是否通过坐标,我们只需检查 2x + 3 = 9y(-6, -1)

2x + 3 = 2(-6) + 3 = -12 + 3 = -9 = 9(-1) -> true

这在处理笔和纸时很容易。

但是,当斜率计算为 (3-1)/(12-3) = 2/9 时,java 中的精度会丢失

使用 Bigdecimal,在计算斜率时给出异常

java.lang.ArithmeticException:非终止十进制扩展;没有精确表示的十进制结果。

并带有双倍

    double slope = (double)(3-1)/(double)(12-3);  //0.2222222222222222
    // Putting (3,1) to get c
    double c = (double)(1) - (double)(slope * 3); //0.33333333333333337
    Hence the equation of the line is y = 0.2222222222222222(x) + 0.33333333333333337

    // to check whether (-6, -1) passes through the above line, put the x coordinate 
    double yCoordinate = 0.2222222222222222* (-6) + 0.33333333333333337;

yCoordinate 出来了,它不是 .所以结果是错误的,但用简单的数学计算得出的答案是正确的。我怎样才能得到预期的结果?-0.9999999999999999-1

Java 双精度 BigDecimal

评论

3赞 Slaw 12/22/2018
检查结果是否在预期结果的一个小增量内。为了阻止被抛出,你必须使用适当的 MathContextArithmeticExceptionBigDecimal
2赞 Marcono1234 12/22/2018
您可以使用提供分数支持的库,例如 Apache Commons Math
0赞 Prasad Karunagoda 12/23/2018
如果您使用 org.junit.Assert.assertEquals(double expected, double actual, double delta) 会怎样?(junit.sourceforge.net/javadoc/org/junit/......)
0赞 Prasad Karunagoda 12/23/2018
您可以使用此 Assert.assertEquals() 将结果与所需的精度进行比较。例如Assert.assertEquals(-1, -0.9999999999, 0.0001)

答:

0赞 Danny Piper 12/23/2018 #1

这足以接近给出一个确切的值,但不是 propper 方式

public double getExactValueDiv(double a,double b){
      double tmp = a/b;
      tmp=Math.round(tmp*1000000000)/1000000000
      return tmp;
}