计算没有平方根的向量单位

时间:2016-02-09 02:36:52

标签: math vector language-agnostic trigonometry

我需要计算任意向量的单位向量。线索是我不想引入浮点错误,所以我不能使用sqrt()函数。为了进行算术运算并且不引入浮点错误,我使用Rational数据类型。

public class Vector3
{
    public Rational X { get; set; }
    public Rational Y { get; set; }
    public Rational Z { get; set; }

    public Vector3(Rational x, Rational y, Rational z)
    {
        X = x;
        Y = y;
        Z = z;
    }
    .....

我的矢量单位计算如下:

    public Vector3 Unit()
    {
        if (this.Length() == 0)
            return new Vector3(0, 0, 0);
        return this.DividedBy(this.Length());
    }

    public Rational Length()
    {
        return Sqrt(Dot(this).ToDouble());
    }

    public Rational Dot(Vector3 a)
    {
        return this.X * a.X + this.Y * a.Y + this.Z * a.Z;
    }

问题是Sqrt()方法,因为我必须将我的Rational转换为double。而且,Sqrt()产生无理数。所以我在输入和sqrt函数的输出中可能出现舍入错误。

所以我需要计算没有平方根的向量的长度。这可能吗?

4 个答案:

答案 0 :(得分:2)

不幸的是,你不能在这里做你想做的事,因为平方根通常(并且很有名)是不合理的。

如果你想坚持使用精确的算术,你可以通过保持你的高阶值来处理它,在一种扩展的有理数据结构中 - 一种代数几何事物。这条路径有其局限性,因为结果的多项式阶数通常是参数阶数的总和......

我认为CGAL提供了类似这样的选项。无论如何,如果您对几何数学感兴趣,但担心浮点错误,那么看看CGAL应该是一种教育。

答案 1 :(得分:1)

抱歉,没有平方根就无法完成。你对完善错误的担心被夸大了。

你可以用最小化错误的方式进行计算,比如这样(Java-ish语法; JDK中没有这样的Math.max,但是你明白了):

public double magnitude(double x, double y, double z) {
    double maxComponent = Math.max(Math.abs(x), Math.abs(y), Math.abs(z));
    double rx = x/maxComponent;
    double ry = y/maxComponent;
    double rz = z/maxComponent;
    return maxComponent*Math.sqrt(rx*rx + ry*ry + rz*rz);
}

答案 2 :(得分:1)

如果您要解决的问题是对浮点错误敏感(我之前已经处理过一些问题),您是否有可能指定您愿意接受的容忍程度?例如,将其设置为输入数据集的精度?

假设这是可能的,我的建议是用一个已知准确达到一定容差的近似值替换sqrt(x)调用。

例如,您可以将其近似为寻根问题X ^ 2 - S = 0的解决方案。鉴于函数严格增加并且在正半平面上表现良好,您可以实现说二分或Newton-Raphson方法并根据公差终止它。

希望你发现它有用,即使它不能解决你的问题。

答案 3 :(得分:0)

有时可以删除sqrt:

对于通常需要单位向量的向量函数,有时可以通过一些聪明的数学来绕过sqrt。矢量投影就是一个很好的例子。

使用sqrt:

将向量a投影到向量b上
  • (a / sqrt(dot(b,b))* b

将矢量a投影到不带sqrt的矢量b上:

  • (dot(a,b)/ dot(b,b))* b

额外的点(a,b)消除了对sqrt的需要。 但是花费3倍和2倍(对于矢量3)所以它不是免费的。