java舍入误差规律_java – 如何在此三角区域计算中避免舍入误差?

我试图用顶点计算三角形的面积

{{0,1000000000},{1,0},{0,-1000000000}}

很容易看出这个三角形的面积应该是1,000,000,000,但是当我尝试使用Heron公式或Shoelace公式计算Java中的面积时,我得到该区域的0.

我很确定这是由于使用双打时的舍入误差,但我不知道如何继续.有什么指针吗?

程序:

private static double areaShoelace(int[][] v) {

return 0.5 * Math.abs(v[0][0]*v[1][1] + v[1][0]*v[2][1] + v[2][0]*v[0][1] +

v[1][0]*v[0][1] + v[2][0]*v[1][1] + v[0][0]*v[2][1]);

}

private static double areaHeron(double a, double b, double c) {

double p = (a + b + c) / 2.0d;

return Math.sqrt(p * (p - a) * (p - b) * (p - c));

}

private static double length(int[] a, int [] b) {

return Math.hypot(a[0] - b[0], a[1] - b[1]);

}

public static void main(String[] args) {

int[][] tri = new int[][]{{0,1000000000},{1,0},{0,-1000000000}};

System.out.println(areaShoelace(tri));

System.out.println(areaHeron(length(tri[0], tri[1]), length(tri[1],tri[2]), length(tri[0],tri[2])));

}

输出:

0.0

0.0

解决方法:

这里实际上有2个不同的错误.

在你的shoelace formula实现中,一些迹象是不正确的(一半应该是负面的).一旦你解决了这个问题,你应该在这种情况下得到正确的答案,但是你应该注意到乘法和加法是使用整数运算来执行的,这可能会导致大数字溢出.

如果将这些更改为浮点运算,将它们分组以减少运算次数和破坏性取消的可能性也是有意义的,我建议

0.5*Math.abs(v[0][0]*(v[1][1] - v[2][1]) + v[1][0]*(v[2][1] - v[0][1]) +

v[2][0]*(v[0][1] - v[1][1]))

但是在这种情况下,你的问题甚至在此之前就出现了:Math.hypot(1,1000000000)的结果在数值上等于1000000000(剩余的数字会丢失到浮点舍入),因此当输入到Heron的公式时(即使精确计算),将给出0.

标签:java,floating-point,precision,area

来源: https://codeday.me/bug/20190829/1758182.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值