使用double in Java计算截锥体侧面时如何处理浮点精度

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

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

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

目前我在做什么:
1. 计算截锥长度
2.计算截锥体的侧面

我的问题:
由于精度损失,假设减去 2 个具有相似大小的浮点数是有问题的。 (我没有 运行 进入这个问题)

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

我发现/想到的可能性:
- 使用 BigDecimal(我不想这样做,因为 运行 时间更长)
- 将 (r1-r2)*(r1-r2) 替换为 r1^2 - 2*r1*r2 + r2^2
- 检查两个 double 值的接近程度,如果非常接近则假设它们的差异为 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;
}

希望有人能帮助我:)

double 对于任何实际甚至 not-so-practical 用途来说都足够准确。因此,除非您的圆锥描述了从地球一直到半人马座阿尔法星的光学 telescope 的视野,否则您不应该有任何精度问题。

我可以向您指出,您计算 length 的方法是先求平方根,然后在使用它之前再次求平方,因此消除那对不必要的计算可能会以某种方式改善情况,但我怀疑这是你的问题。

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

无论如何,你为什么不提供一个self-contained,可编译的例子,和实际的输入值,实际的输出值,以及你的期望值,我们可以更深入地研究它。