任意维数学向量的一类

时间:2012-06-02 12:50:57

标签: java math vectormath

我想写一个数学向量类(保持实数)。我认为Vector操作几乎与vector的维度无关,所以不是像Vector2DVector3DVector4D那样编写类,我只是想写一个Vector课程。

现在的问题是我不能将2D矢量与4D矢量相乘,所以我想到了一个字段dimension。但现在我必须检查每次操作,所以我问自己是否可以做得更好。这是仿制药在我脑海中浮现的。但是我必须再做Vector<? extends Dimension>之类的事情,其中​​Dimension只是Dimension.One的基类,Dimension.Two等等,这意味着,我必须写一个我想要使​​用vectos的每个维度的Dimension类。

所以我的问题:

有没有办法为任意维度的向量编写一个类而不必在运行时检查维度?

4 个答案:

答案 0 :(得分:2)

如果我理解你的问题,那么答案是你不能同时拥有这两个问题。您可以使用类型系统来确保正确的维度,然后最终会出现大量的显式类型(泛型对您没有帮助),或者您每次执行操作时都使用状态来跟踪维度并执行动态检查。 由于向量的“维度”是它所包含的元素数量,因此将在底层数据结构中以某种方式表示。例如,如果使用列表将值存储在向量中,则列表将知道它包含的元素数量。因此,进行简单的运行时检查很便宜,并且您可以在尺寸不匹配时抛出异常。与基于类型的解决方案相比,该解决方案更灵活,更易于编程。

答案 1 :(得分:2)

如果向量不兼容,您可以在Dimension类中嵌入执行检查的方法并抛出Runtime Exception。然后让Dimension中的每个方法都调用此方法。现在,使用 Dimension类的代码将不会出现问题。

答案 2 :(得分:0)

你可以编写一个带有一些有趣泛型的Vector类

public static class Vector<V extends Vector<V>>{
    protected double[] components;
    public final int dimensions;
    private Class<V> klass;

    protected Vector(int d, Class<V> klass) {
        this.klass = klass;
        this.components = new double[d];
    }

    public double get(int x) { return components[x] }
    protected void set(int x, double d) { components[x] = d }

    public V clone() {
        try {
            V c = klass.newInstance();
            c.components = this.components.clone();
            return c;
        }
        catch(InstantiationException e1) {}
        catch(IllegalAccessException e2) {}
        return null;
    }

    public V add(V that) {
        V sum = this.clone();
        for(int i = 0; i < dimensions; i++)
            sum.components[i] += that.components[i];
        return sum;
    }

}

然后得出每个案例:

public static class Vector2D extends Vector<Vector2D>{
    public Vector2D() { 
        super(2, Vector2D.class);
    }
    public Vector2D(double x, double y) { 
        this();
        set(0, x);
        set(1, y);
    }
}
public static class Vector3D extends Vector<Vector3D>{
    public Vector3D() { 
        super(3, Vector3D.class);
    }
    public Vector3D(double x, double y, double z) { 
        this();
        set(0, x);
        set(1, y);
        set(2, z);
    }
}
public static class Vector4D extends Vector<Vector4D>{
    public Vector4D() { 
        super(4, Vector4D.class);
    }
    public Vector4D(double w, double x, double y, double z) { 
        this();
        set(0, w);
        set(1, x);
        set(2, y);
        set(3, z);
    }
}

毕竟,有特殊情况 - 例如,交叉产品仅存在于3维和7维。每个实现都解决了这个问题。

答案 3 :(得分:0)

要明确我为什么要使用泛型(这就是为什么我将其作为答案发布的原因):

Dimension.java:

public class Dimension {
    class ONE extends Dimension {}
    class TWO extends Dimension {}
    class THREE extends Dimension {}
    // [...]
}

Vector.java:

public class Vector<D extends Dimension> {
    private double[] elements;

    public Vector(double _elmts) {
        elements = _elmts;
    }

    public void add(Vector<D> v) { /*...*/ }
    public void subtract(Vector<D> v) { /*...*/ }
}

但正如我的问题所提到的,我必须创建几个类,这是我想要首先防止的。它也相当难看。除了信任用户之外,没有办法确保elements具有正确的维度。

我想这与Eric的答案非常相似。