计算浮点误差限制

时间:2016-01-31 16:33:49

标签: c# floating-point geometry

我有几何算法,我正在努力解决浮点不准确问题。 例如,我正在计算一个点位于左/右/平面上(C#):

    const double Epsilon = 1e-10;
    internal double ComputeDistance(Vector3D v)
    {
        Vector3D normal = Plane.Normal;
        Vertex v0 = Plane.Origin;
        double a = normal.X;
        double b = normal.Y;
        double c = normal.Z;
        double d = -(a * v0.X + b * v0.Y + c * v0.Z);

        return a * v.X + b * v.Y + c * v.Z + d;
    }

    internal string DistanceSign(Vector3D v)
    {
        var distance = ComputeDistance(v);
        return (distance > Epsilon ? "left" : (distance < -Epsilon ? "right" : "on"));
    }

如代码所示,我使用固定的Epsilon值。

但我不相信这个固定的epsilon,因为我不知道浮点错误的大小。如果fp错误大于我的epsilon间隔,那么我的算法将失败。 我怎样才能让它健壮?我在互联网上搜索过但到目前为止还没有找到解决方案。我读过“每个计算机科学家应该知道的关于浮点算术的内容”,它描述了为什么会出现fp错误而不是如何实际解决它们。

修改

这是一个看似不起作用的shewchuk谓词:

        double[] pa = {0, 0};
        double[] pb = {2 * Double.Epsilon, 0};
        double[] pc = { 0, Double.Epsilon };

        Assert.IsTrue(GeometricPredicates.Orient2D(pa, pb, pc) > 0);

断言失败,因为Orient2D返回0.代码为here

EDIT2

是否应该可以通过使用机器epsilon来计算误差?根据维基百科,由于四舍五入,机器epsilon是一个上限。对于double,它是2 ^ -53。所以,当我接受它时,我有一个算术计算:     double x = y + z 那么最大误差应该是2 ^ -53。这个事实不应该能够计算出合适的epsilon吗?所以两个重写我的方法:

    double const Machine_Eps = 1.11022302462516E-16 // (2^-53)
    double Epsilon = Machine_Eps; 
    internal double ComputeDistance(Vector3D v)
    {
        Vector3D normal = Plane.Normal;
        Vertex v0 = Plane.Origin;
        double a = normal.X;
        double b = normal.Y;
        double c = normal.Z;

        // 3 multiplications + 2 additions = maximum of 5*Machine_Eps
        double d = -(a * v0.X + b * v0.Y + c * v0.Z);

        // 3 multiplications + 3 additions = maximum of 6*Machine_Eps
        Epsilon = 11 * Machine_Eps;
        return a * v.X + b * v.Y + c * v.Z + d;
    }

    internal string DistanceSign(Vector3D v)
    {
        var distance = ComputeDistance(v);
        return (distance > Epsilon ? "left" : (distance < -Epsilon ? "right" : "on"));
    }

好的,现在你可以告诉我我有多错。 :)

0 个答案:

没有答案