哦,OpenMesh矢量算法的精度在哪里?

时间:2014-07-28 14:30:31

标签: c++ double

使用double s我希望有大约15个小数点的精度。我知道很多十进制数是not exactly representable in floating point notation,所以我会得到1/3的近似值。但是,使用double我会期望近似值大约为15个小数点。我还希望在算术时保持这种准确度。

但是,在下面的示例中,我尝试使用由Heron's formula支持的OpenMesh::VectorDataT<double,3>OpenMesh::Vec3d来计算三角形的面积,最终结果只是准确的到5个小数点。

正确的结果是area = 8.19922e-8,但我得到area=8.1992238711962083e-8。有什么想法来自哪里?

这可能是由Heron公式中的不稳定性造成的,这是一个很好的建议,但不幸的是在这个例子中并非如此。我添加了代码,可以为那些可能感兴趣的人计算Heron的稳定变化。在此示例中,u.norm()>v.norm()>w.norm()

#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>

int main()
{
    //triangle vertices
    OpenMesh::Vec3d x(0.051051, 0.057411, 0.001355);
    OpenMesh::Vec3d y(0.050981, 0.057337, -0.000678);
    OpenMesh::Vec3d z(0.050949, 0.057303, 0.0);

    //edge vectors
    OpenMesh::Vec3d u = x-y;
    OpenMesh::Vec3d v = x-z;
    OpenMesh::Vec3d w = y-z;

    //Heron's Formula
    double semiP = (u.norm() + v.norm() + w.norm())/2.0; 
    double area = sqrt(semiP * (semiP - u.norm()) * (semiP - v.norm()) * (semiP - w.norm()) ); 

    //Heron's Formula for small angles
    double areaSmall = sqrt((u.norm() + (v.norm()+w.norm()))*(w.norm()-(u.norm()-v.norm()))*(w.norm()+(u.norm()-v.norm()))*(u.norm()+(v.norm()-w.norm())))/4.0;
}

3 个答案:

答案 0 :(得分:3)

苍鹭的公式在数值上不稳定。如果你有一个非常“扁平”的三角形,角度很小,那么两个小边的总和几乎就是长边,所以其中一个术语变得非常小。例如,如果ab是小方,

(s - c)

会非常小,因为

s = (a + b + c)/2

几乎等于c

wikipedia article about herons formula提到了一个稳定的选择:

安排双方a > b > c并使用

A = 1/4*sqrt((a + (b + c))*(c - (a - b))*(c + (a - b))*(a + (b - c)))

答案 1 :(得分:3)

小数点后75位,三角形的正确区域为

0.000000081992238711963087279421583920293974467992093148008322378721298327364.

如果我用它们的十进制等值替换九个double常量,我得

0.000000081992238711965902754749500279615357792172906541206211853522524016959

看起来你没有得到你所期待的东西,因为你期待一些不合理的东西。

答案 2 :(得分:2)

如果值完全相互接近,任何涉及减法的计算都将导致精度损失。你对这次减法有多少有效数字?

  1.23456789012345
- 1.23456789000000
  ----------------
  0.00000000012345

两个操作数都有15位精度,但结果只有5位。