在 Java 中使用 double 计算视锥体的侧面时如何处理浮点精度

How to deal with floating-point accuracy when calculating the lateral surface of a frustum cone using double in Java

提问人:bunting 提问时间:7/14/2019 最后编辑:bunting 更新时间:7/15/2019 访问量:59

问:

我正在尝试使用下面的代码计算视锥体的侧表面。

输入:2 个节点,包含 x、y、z 值(绝对位置)和半径(位置半径)均为双精度

到目前为止我正在做什么:
1. 计算视锥体的长度
2.计算视锥体的侧表面

我的问题:
假设减去 2 个具有相似大小的浮点数是有问题的,因为精度损失。(我没有遇到这个问题)

我的问题:
我能做些什么来改善最终结果?

我发现/想到的可能性:
- 使用 BigDecimal(我不想这样做,因为运行时间更长) - 将 (r1-r2)*(r1-r2)
替换为 r1^2 - 2*r1*r2 + r2^2
- 检查两个双精度值的接近程度,如果非常接近,则假设它们的差值为 0。这甚至会提高我最终结果的准确性吗?减法结果的绝对误差不是比假设为 0 的结果小吗?

public static double calculateLateralSurface(Node node1, Node node2) {
    double x, y, z, length, r1, r2, lateralSurface;

    // calculate length of frustum cone
    x = node1.getPosX() - node2.getPosX();
    y = node1.getPosY() - node2.getPosY();
    z = node1.getPosZ() - node2.getPosZ();
    length = Math.sqrt(x * x + y * y + z * z);
    r1 = node1.getRadius();
    r2 = node2.getRadius();

    // calculate lateral surface of frustum cone
    lateralSurface = (r1+r2)*Math.PI*Math.sqrt((r1-r2)*(r1-r2)+length*length);
    return lateralSurface;
}

我希望有人能帮助我:)

Java 浮动精度 几何曲面

评论

0赞 JB Nizet 7/14/2019
我认为你只需要接受你不会得到一个绝对准确的结果。问题到底是什么?
0赞 Eric Postpischil 7/14/2019
显示一个最小的可重现示例,包括精确输入(如果它有浮点数,则准确显示它们的值,至少使用足够的数字来唯一区分该值与相邻的可表示值)、确切的输出和所需的输出。
0赞 Eric Postpischil 7/14/2019
不,假设两个接近数字的差值为零不是一个好主意。如果两个数字相近(每个数字至少是另一个数字的一半),则减去它们的结果没有错误。结果中存在的任何误差都存在于减法之前的操作数中。double

答:

2赞 Mike Nakis 7/14/2019 #1

double对于任何实际甚至不那么实用的用途来说,都有足够的准确性。因此,除非你的锥体描述了从地球一直到半人马座阿尔法星的光学望远镜的视场,否则你不应该有任何精度问题。

我可以向你指出,你是通过取平方根来计算的,只是为了在以后使用它之前再次平方它,所以消除不必要的一对计算可能会以某种方式改善事情,但我怀疑这是你的问题。length

因此,如果您的结果看起来不正确,那么可能是错误造成的,而不是 的精度。double

无论如何,您为什么不提供一个独立的、可编译的示例,以及实际输入值、实际输出值和您的期望值,我们可以更深入地研究它。

评论

0赞 LukeTheNuke 7/15/2019
好!没有看到我不必要的长度计算。感谢这个独立的、可编译的例子:我的问题是假设的。恐怕我可能会遇到这个问题,因为我的函数参数变化很大。对不起,我刚刚意识到我应该在 softwareengineering.stackexchange.com 问我的问题,对吗?
0赞 Mike Nakis 7/15/2019
这种类型的问题对于stackoverflow来说很好。