1. 简介
SuanShu 是一个用于数值分析、统计学、求根、线性代数、优化等领域的 Java 数学库。它不仅支持实数运算,还支持复数运算。
该库提供开源版本和商业授权版本两种形式。商业版本根据用途分为学术版、商业版和贡献者版。不同版本的授权方式有所区别。
⚠️ 注意:本文中的示例使用的是经过 fork 的商业授权版本,并通过 pom.xml 引入。目前开源版本尚未发布到 Maven 中央仓库;而商业版本需要运行一个许可证服务器。因此,GitHub 上并没有针对这个库的单元测试代码。
2. SuanShu 配置
我们首先在项目的 pom.xml 文件中添加以下依赖项:
<dependency>
<groupId>io.deephaven</groupId>
<artifactId>SuanShu</artifactId>
<version>0.1.0</version>
</dependency>
3. 向量操作
SuanShu 提供了对稠密向量(dense vector)和稀疏向量(sparse vector)的支持。
- ✅ 稠密向量:大多数元素为非零值。
- ❌ 稀疏向量:大多数元素为零值。
稠密向量底层使用 Java 数组存储实数或复数;而稀疏向量则通过“索引-值”条目(entry)数组进行存储,这样在处理大规模且多数元素为零的向量时能显著节省内存空间。这是许多数学库处理大向量的标准做法。
3.1. 向量相加
两个向量相加非常简单,调用 add()
方法即可:
public void addingVectors() throws Exception {
Vector v1 = new DenseVector(new double[] {1, 2, 3, 4, 5});
Vector v2 = new DenseVector(new double[] {5, 4, 3, 2, 1});
Vector v3 = v1.add(v2);
log.info("Adding vectors: {}", v3);
}
输出结果为:
[6.000000, 6.000000, 6.000000, 6.000000, 6.000000]
此外,还可以使用 add(double)
方法将一个常数加到所有元素上。
3.2. 缩放向量
向量缩放(即乘以一个标量)也很容易实现:
public void scaleVector() throws Exception {
Vector v1 = new DenseVector(new double[]{1, 2, 3, 4, 5});
Vector v2 = v1.scaled(2.0);
log.info("Scaling a vector: {}", v2);
}
输出结果:
[2.000000, 4.000000, 6.000000, 8.000000, 10.000000]
3.3. 向量内积
计算两个向量的内积只需调用 innerProduct(Vector)
方法:
public void innerProductVectors() throws Exception {
Vector v1 = new DenseVector(new double[]{1, 2, 3, 4, 5});
Vector v2 = new DenseVector(new double[]{5, 4, 3, 2, 1});
double inner = v1.innerProduct(v2);
log.info("Vector inner product: {}", inner);
}
3.4. 错误处理机制
SuanShu 在执行向量运算前会自动校验维度是否匹配。例如,试图将长度为 2 和长度为 3 的向量相加会抛出异常:
public void addingIncorrectVectors() throws Exception {
Vector v1 = new DenseVector(new double[] {1, 2, 3});
Vector v2 = new DenseVector(new double[] {5, 4});
Vector v3 = v1.add(v2);
}
运行上述代码会得到如下异常:
Exception in thread "main" com.numericalmethod.suanshu.vector.doubles.IsVector$SizeMismatch: vectors do not have the same size: 3 and 2
at com.numericalmethod.suanshu.vector.doubles.IsVector.throwIfNotEqualSize(IsVector.java:101)
at com.numericalmethod.suanshu.vector.doubles.dense.DenseVector.add(DenseVector.java:174)
at com.baeldung.suanshu.SuanShuMath.addingIncorrectVectors(SuanShuMath.java:21)
at com.baeldung.suanshu.SuanShuMath.main(SuanShuMath.java:8)
4. 矩阵操作
除了向量外,SuanShu 还提供了完整的矩阵运算支持,包括稠密矩阵和稀疏矩阵,以及实数和复数类型。
4.1. 矩阵相加
矩阵相加与向量相加类似:
public void addingMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{3, 2, 1},
{6, 5, 4}
});
Matrix m3 = m1.add(m2);
log.info("Adding matrices: {}", m3);
}
4.2. 矩阵相乘
矩阵相乘也由库自动处理:
public void multiplyMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{1, 4},
{2, 5},
{3, 6}
});
Matrix m3 = m1.multiply(m2);
log.info("Multiplying matrices: {}", m3);
}
一个 2×3 矩阵乘以一个 3×2 矩阵的结果是一个 2×2 矩阵。
为了验证库对矩阵维度的检查机制,我们尝试一次非法操作:
public void multiplyIncorrectMatrices() throws Exception {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2, 3},
{4, 5, 6}
});
Matrix m2 = new DenseMatrix(new double[][]{
{3, 2, 1},
{6, 5, 4}
});
Matrix m3 = m1.multiply(m2);
}
运行后会抛出如下异常:
Exception in thread "main" com.numericalmethod.suanshu.matrix.MatrixMismatchException:
matrix with 3 columns and matrix with 2 rows cannot multiply due to mis-matched dimension
at com.numericalmethod.suanshu.datastructure.DimensionCheck.throwIfIncompatible4Multiplication(DimensionCheck.java:164)
at com.numericalmethod.suanshu.matrix.doubles.matrixtype.dense.DenseMatrix.multiply(DenseMatrix.java:374)
at com.baeldung.suanshu.SuanShuMath.multiplyIncorrectMatrices(SuanShuMath.java:98)
at com.baeldung.suanshu.SuanShuMath.main(SuanShuMath.java:22)
4.3. 求矩阵的逆
手动计算矩阵的逆很繁琐,但 SuanShu 提供了便捷的方法:
public void inverseMatrix() {
Matrix m1 = new DenseMatrix(new double[][]{
{1, 2},
{3, 4}
});
Inverse m2 = new Inverse(m1);
log.info("Inverting a matrix: {}", m2);
}
我们可以通过将原矩阵与其逆矩阵相乘来验证结果是否为单位矩阵:
log.info("Verifying a matrix inverse: {}", m1.multiply(m2));
5. 多项式求解
SuanShu 还支持多项式的创建、求值和求根。
5.1. 创建多项式
可以通过指定系数来构造一个多项式。例如,构造多项式 3x² - 5x + 1:
public Polynomial createPolynomial() {
return new Polynomial(new double[]{3, -5, 1});
}
注意:系数顺序从最高次幂开始。
5.2. 计算多项式值
使用 evaluate()
方法可以计算多项式在某个点的值,支持实数和复数输入:
public void evaluatePolynomial(Polynomial p) {
log.info("Evaluating a polynomial using a real number: {}", p.evaluate(5));
log.info("Evaluating a polynomial using a complex number: {}", p.evaluate(new Complex(1, 2)));
}
输出结果:
51.0
-13.000000+2.000000i
5.3. 求多项式的根
SuanShu 内置了多种经典算法来求解多项式的根。根据多项式的最高次数,PolyRoot
类会自动选择最优算法:
public void solvePolynomial() {
Polynomial p = new Polynomial(new double[]{2, 2, -4});
PolyRootSolver solver = new PolyRoot();
List<? extends Number> roots = solver.solve(p);
log.info("Finding polynomial roots: {}", roots);
}
输出结果:
[-2.0, 1.0]
说明该多项式有两个实根:-2 和 1。当然,也支持复数根。
6. 总结
本文只是对 SuanShu 数学库的一个初步介绍。它涵盖了向量、矩阵、多项式等多个方面,功能强大且接口清晰。
一如既往,完整源码可以在 GitHub 上找到。