前端 math.js 快速上手入门教程
本文介绍 JavaScript 数学库 math.js 的快速入门方法。内容包括安装配置、基础运算、矩阵与复数处理、表达式解析及可视化集成。重点讲解高精度计算、类型一致性、性能优化等常见问题及解决方案,并提供单元测试示例与最佳实践建议,辅助开发者高效完成数学计算任务。

本文介绍 JavaScript 数学库 math.js 的快速入门方法。内容包括安装配置、基础运算、矩阵与复数处理、表达式解析及可视化集成。重点讲解高精度计算、类型一致性、性能优化等常见问题及解决方案,并提供单元测试示例与最佳实践建议,辅助开发者高效完成数学计算任务。

math.js 的基本概念和用途math.js 的安装与配置math.js 进行基本数学运算math.js 的高级功能:矩阵、复数、表达式解析等math.js 使用陷阱math.js 是一个强大的 JavaScript 数学库,它提供了丰富的数学函数、数据类型(如矩阵、复数)和表达式解析器。与原生 JavaScript 相比,math.js 提供了更精确的计算能力和更丰富的数学功能。
| 特性 | 原生 JavaScript | math.js |
|---|---|---|
| 精度 | 受限于浮点数精度 | 高精度计算支持 |
| 数据类型 | 基本数值类型 | 矩阵、复数、分数等 |
| 功能 | 基础数学运算 | 丰富的数学函数库 |
| 表达式解析 | 不支持 | 内置表达式解析器 |
npm install mathjs
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.7.0/math.min.js"></script>
import * as math from 'mathjs';
// 基本运算
const result1 = math.add(2, 3); // 5
const result2 = math.subtract(5, 2); // 3
const result3 = math.multiply(4, 3); // 12
const result4 = math.divide(10, 2); // 5
// 高精度计算
const preciseResult = math.evaluate('0.1 + 0.2'); // 0.3 (不是 0.30000000000000004)
| 函数 | 说明 | 示例 |
|---|---|---|
math.sqrt(x) | 平方根 | math.sqrt(16) → 4 |
math.pow(x, y) | 幂运算 | math.pow(2, 3) → 8 |
math.sin(x) | 正弦函数 | math.sin(math.pi / 2) → 1 |
math.log(x) | 自然对数 | math.log(math.e) → 1 |
// 创建矩阵
const matrixA = math.matrix([[1, 2], [3, 4]]);
const matrixB = math.matrix([[5, 6], [7, 8]]);
// 矩阵加法
const matrixSum = math.add(matrixA, matrixB);
console.log(math.format(matrixSum)); // [[6, 8], [10, 12]]
// 矩阵乘法
const matrixProduct = math.multiply(matrixA, matrixB);
console.log(math.format(matrixProduct)); // [[19, 22], [43, 50]]
| 操作 | 说明 | 示例 |
|---|---|---|
math.transpose(matrix) | 转置矩阵 | math.transpose([[1, 2], [3, 4]]) → [[1, 3], [2, 4]] |
math.det(matrix) | 计算行列式 | math.det([[1, 2], [3, 4]]) → -2 |
math.inv(matrix) | 计算逆矩阵 | math.inv([[1, 2], [3, 4]]) → [[-2, 1], [1.5, -0.5]] |
// 创建复数
const complex1 = math.complex(3, 4); // 3 + 4i
const complex2 = math.complex('2 + 5i'); // 2 + 5i
// 复数运算
const complexSum = math.add(complex1, complex2);
console.log(math.format(complexSum)); // 5 + 9i
const complexProduct = math.multiply(complex1, complex2);
console.log(math.format(complexProduct)); // -14 + 23i
| 属性 | 说明 | 示例 |
|---|---|---|
re | 实部 | complex1.re → 3 |
im | 虚部 | complex1.im → 4 |
abs() | 模长 | complex1.abs() → 5 |
// 表达式解析
const result = math.evaluate('sqrt(3^2 + 4^2)');
console.log(result); // 5
// 变量支持
const scope = { x: 2, y: 3 };
const result2 = math.evaluate('x^2 + y^2', scope);
console.log(result2); // 13
// 自定义函数
math.evaluate('f(x) = x^2 + 2*x + 1');
const result3 = math.evaluate('f(3)');
console.log(result3); // 16
// 表达式编译以提高性能
const expr = math.compile('x^2 + 2*x + 1');
const result4 = expr.evaluate({ x: 3 });
console.log(result4); // 16
虽然 math.js 本身不提供绘图功能,但它可以与绘图库(如 Chart.js)结合使用。
// 生成数据点
const xValues = math.range(-10, 10, 0.1).toArray();
const yValues = xValues.map(x => math.evaluate('x^2', { x }));
// 使用 Chart.js 绘制图表
// const ctx = document.getElementById('myChart').getContext('2d');
// new Chart(ctx, {
// type: 'line',
// data: {
// labels: xValues,
// datasets: [{
// label: 'y = x^2',
// data: yValues,
// borderColor: 'rgb(75, 192, 192)',
// tension: 0.1
// }]
// }
// });
结合 Three.js 等 3D 库可以实现更复杂的可视化。
// 生成 3D 数据点
const data = [];
for (let x = -5; x <= 5; x += 0.5) {
for (let y = -5; y <= 5; y += 0.5) {
const z = math.evaluate('sin(sqrt(x^2 + y^2))', { x, y });
data.push([x, y, z]);
}
}
使用 Jest 进行单元测试。
// math.test.js
const math = require('mathjs');
test('addition works correctly', () => {
expect(math.add(2, 3)).toBe(5);
});
test('matrix multiplication works correctly', () => {
const A = math.matrix([[1, 2], [3, 4]]);
const B = math.matrix([[5, 6], [7, 8]]);
const result = math.multiply(A, B);
const expected = math.matrix([[19, 22], [43, 50]]);
expect(math.deepEqual(result, expected)).toBe(true);
});
test('division by zero throws error', () => {
expect(() => math.divide(1, 0)).toThrow();
});
test('sqrt of negative number returns complex', () => {
const result = math.sqrt(-4);
expect(result).toBeInstanceOf(math.Complex);
expect(result.re).toBe(0);
expect(result.im).toBe(2);
});
问题:以为用了 math.js 就不会有精度问题
解决方案:使用 math.bignumber 进行高精度计算
// 错误做法
const result1 = math.evaluate('0.1 + 0.2'); // 0.30000000000000004
// 正确做法
const result2 = math.add(math.bignumber(0.1), math.bignumber(0.2)); // 0.3
问题:JavaScript Number 与 math.js 类型混用 解决方案:统一使用 math.js 类型
// 错误做法
const result1 = math.add(0.1, math.bignumber(0.2)); // 类型不匹配
// 正确做法
const result2 = math.add(math.bignumber(0.1), math.bignumber(0.2));
问题:忘记 math.js 矩阵索引从 0 开始 解决方案:注意索引范围
// 错误做法
const matrix = math.matrix([[1, 2], [3, 4]]);
const value = matrix.get([1, 1]); // 实际获取的是第 2 行第 2 列
// 正确做法
const value = matrix.get([0, 0]); // 获取第 1 行第 1 列
问题:表达式中变量未定义 解决方案:正确传递作用域
// 错误做法
const result = math.evaluate('x + y'); // ReferenceError: x is not defined
// 正确做法
const scope = { x: 1, y: 2 };
const result = math.evaluate('x + y', scope);
问题:自定义函数覆盖了内置函数 解决方案:避免使用内置函数名
// 错误做法
math.evaluate('sin(x) = x^2'); // 覆盖了内置 sin 函数
// 正确做法
math.evaluate('mysin(x) = x^2');
问题:在异步操作中使用 math.js 解决方案:确保在正确上下文中使用
// 错误做法
setTimeout(() => {
const result = math.add(1, 2); // 可能出现上下文问题
}, 1000);
// 正确做法
setTimeout(() => {
const math = require('mathjs');
const result = math.add(1, 2);
}, 1000);
问题:大量创建 math.js 对象未释放 解决方案:合理管理对象生命周期
// 错误做法
for (let i = 0; i < 1000000; i++) {
const matrix = math.matrix([...]); // 可能导致内存泄漏
}
// 正确做法
// 使用完后确保对象可以被垃圾回收
问题:频繁使用 math.evaluate
解决方案:使用 math.compile 预编译表达式
// 错误做法
for (let i = 0; i < 10000; i++) {
const result = math.evaluate('x^2 + 2*x + 1', { x: i }); // 性能差
}
// 正确做法
const expr = math.compile('x^2 + 2*x + 1');
for (let i = 0; i < 10000; i++) {
const result = expr.evaluate({ x: i }); // 性能好
}
问题:角度单位混淆(度 vs 弧度) 解决方案:明确指定单位
// 错误做法
const result1 = math.sin(90); // 90 弧度,不是 90 度
// 正确做法
const result2 = math.sin(math.unit(90, 'deg')); // 90 度
问题:导入方式不正确导致功能缺失 解决方案:使用正确的导入方式
// 错误做法
import math from 'mathjs'; // 可能导入不完整
// 正确做法
import * as math from 'mathjs'; // 导入所有功能
| 功能类别 | 原生 JavaScript | math.js | 优势 |
|---|---|---|---|
| 基本运算 | ✅ 支持 | ✅ 支持 | math.js 精度更高 |
| 高精度计算 | ❌ 不支持 | ✅ 支持 BigNumber | math.js 支持任意精度 |
| 矩阵运算 | ❌ 不支持 | ✅ 完整支持 | math.js 提供完整矩阵库 |
| 复数运算 | ❌ 不支持 | ✅ 完整支持 | math.js 内置复数类型 |
| 表达式解析 | ❌ 不支持 | ✅ 强大解析器 | math.js 支持复杂表达式 |
| 单位转换 | ❌ 不支持 | ✅ 支持多种单位 | math.js 内置单位系统 |
| 统计函数 | ❌ 基础支持 | ✅ 丰富函数库 | math.js 提供更多统计函数 |
| 微积分 | ❌ 不支持 | ✅ 支持符号计算 | math.js 支持导数、积分 |
| 分数运算 | ❌ 不支持 | ✅ 支持分数类型 | math.js 保持分数精度 |
| 性能优化 | ❌ 无优化 | ✅ 表达式编译 | math.js 支持预编译优化 |
// 示例:表达式 '2 + 3 * 4' 的处理过程
// 1. 词法分析:['2', '+', '3', '*', '4']
// 2. 语法分析:AST (加法节点,左子树是 2,右子树是乘法节点)
// 3. 语义分析:检查操作数类型
// 4. 优化:无
// 5. 执行:先计算 3*4=12,再计算 2+12=14
// 伪代码示例
function multiplyMatrix(A, B) {
// 1. 维度检查
if (A.columns !== B.rows) throw new Error('矩阵维度不匹配');
// 2. 初始化结果矩阵
const result = createMatrix(A.rows, B.columns);
// 3. 三重循环
for (let i = 0; i < A.rows; i++) {
for (let j = 0; j < B.columns; j++) {
let sum = 0;
for (let k = 0; k < A.columns; k++) {
sum += A.get([i, k]) * B.get([k, j]);
}
result.set([i, j], sum);
}
}
// 4. 返回结果
return result;
}
// 梯形法则实现
function trapezoidalRule(func, a, b, n) {
const h = (b - a) / n; // 步长
let sum = (func(a) + func(b)) / 2; // 端点值
for (let i = 1; i < n; i++) {
sum += func(a + i * h); // 中间点值
}
return sum * h; // 乘以步长
}
math.compile 预编译表达式| 实践项目 | 说明 |
|---|---|
✅ 使用 math.bignumber | 处理需要高精度的计算 |
| ✅ 预编译表达式 | 对于重复使用的表达式使用 math.compile |
| ✅ 明确单位 | 使用 math.unit 处理物理量计算 |
| ✅ 类型检查 | 在关键位置添加类型检查 |
| ✅ 异常处理 | 使用 try-catch 处理可能的计算错误 |
| ✅ 内存管理 | 及时释放不再使用的大型对象 |
| ✅ 文档注释 | 为复杂的数学计算添加详细注释 |
| ✅ 单元测试 | 为所有数学函数编写测试用例 |

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online