繁体   English   中英

任意维数学向量的一类

[英]One class for math vectors of arbitrary dimension

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

现在的问题是我无法将2D矢量与4D矢量相乘,所以我想到了一个场dimension 但现在我必须检查每次操作,所以我问自己是否可以做得更好。 这是仿制药在我脑海中浮现的。 但是我又要做一些像Vector<? extends Dimension> Vector<? extends Dimension> ,其中Dimension只是Dimension.OneDimension.Two等的基类,这意味着,我必须为我想要使用vectos的每个维度编写一个Dimension类。

所以我的问题:

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

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

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

你可以编写一个带有一些有趣泛型的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维。 每个实现都解决了这个问题。

为了弄清楚为什么我想使用泛型(它的作用就是为什么我把它作为答案发布):

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的答案非常相似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM