表达式语法 #
本页介绍了 math.js 表达式解析器的语法。它描述了如何使用可用的数据类型、函数、运算符、变量等。
与 JavaScript 的区别 #
math.js 的表达式解析器面向数学受众,而不是编程受众。语法与大多数计算器和数学应用程序相似。这也接近 JavaScript,尽管表达式解析器的语法与 math.js 的低级语法之间存在一些重要区别。区别在于
- 无需在函数和常量前加上
math.*命名空间,只需输入sin(pi / 4)即可。 - 矩阵索引是从 1 开始的,而不是从 0 开始。
- 存在索引和范围运算符,可以更方便地获取和设置矩阵索引,例如
A[2:4, 1]。 - 索引和范围都包含上限。
- 定义函数存在不同的语法。例如:
f(x) = x^2。 - 存在自定义运算符,例如
x + y,而不是add(x, y)。 - 某些运算符不同。例如,
^用于幂运算,而不是按位异或。 - 支持隐式乘法,例如
2 pi,并且有特殊的规则。 - 关系运算符(
<、>、<=、>=、==和!=)是链式连接的,因此表达式5 < x < 10等同于5 < x and x < 10。 - 某些运算符的优先级不同;有关完整列表,请参见下方的优先级表。
- 多表达式结构,例如
a = 1; b = 2; a + b或"a = 1;\n cos(a)\n sin(a)"(其中\n表示换行),会产生一个值的集合(“ResultSet”)。以;结尾的表达式仅为副作用而计算,其值不包含在结果中。
运算符 #
表达式解析器包含所有常见算术运算(如加法和乘法)的运算符。表达式解析器使用传统的运算符中缀表示法:运算符放在其参数之间。圆括号可用于覆盖运算符的默认优先级。
// use operators
math.evaluate('2 + 3') // 5
math.evaluate('2 * 3') // 6
// use parentheses to override the default precedence
math.evaluate('2 + 3 * 4') // 14
math.evaluate('(2 + 3) * 4') // 20
以下是可用的运算符。请注意,几乎所有列出的运算符也都有具有相同含义且可以互换使用的函数形式。例如,x+y 的计算结果始终与 add(x,y) 相同。有关这些等价关系的完整列表,请参见下文的函数部分。
| 运算符 | 名称 | 语法 | 结合性 | 示例 | 结果 |
|---|---|---|---|---|---|
(, ) |
分组 | (x) |
无 | 2 * (3 + 4) |
14 |
[, ] |
矩阵、索引 | [...] |
无 | [[1,2],[3,4]] |
[[1,2],[3,4]] |
{, } |
Object | {...} |
无 | {a: 1, b: 2} |
{a: 1, b: 2} |
, |
参数分隔符 | x, y |
从左到右 | max(2, 1, 5) |
5 |
. |
属性访问器 | obj.prop |
从左到右 | obj={a: 12}; obj.a |
12 |
; |
语句分隔符 | x; y |
从左到右 | a=2; b=3; a*b |
[6] |
; |
行分隔符 | [x; y] |
从左到右 | [1,2;3,4] |
[[1,2],[3,4]] |
\n |
语句分隔符 | x \n y |
从左到右 | a=2 \n b=3 \n a*b |
[2,3,6] |
+ |
加法 | x + y |
从左到右 | 4 + 5 |
9 |
+ |
一元加 | +y |
从右到左 | +4 |
4 |
- |
减法 | x - y |
从左到右 | 7 - 3 |
4 |
- |
一元减 | -y |
从右到左 | -4 |
-4 |
* |
乘法 | x * y |
从左到右 | 2 * 3 |
6 |
.* |
逐元素乘法 | x .* y |
从左到右 | [1,2,3] .* [1,2,3] |
[1,4,9] |
/ |
除法 | x / y |
从左到右 | 6 / 2 |
3 |
./ |
逐元素除法 | x ./ y |
从左到右 | [9,6,4] ./ [3,2,2] |
[3,3,2] |
% |
百分比 | x% |
无 | 8% |
0.08 |
% |
带百分比的加法 | x + y% |
从左到右 | 100 + 3% |
103 |
% |
带百分比的减法 | x - y% |
从左到右 | 100 - 3% |
97 |
% mod |
模运算 | x % y |
从左到右 | 8 % 3 |
2 |
^ |
幂运算 | x ^ y |
从右到左 | 2 ^ 3 |
8 |
.^ |
逐元素幂运算 | x .^ y |
从右到左 | [2,3] .^ [3,3] |
[8,27] |
' |
转置 | y' |
从左到右 | [[1,2],[3,4]]' |
[[1,3],[2,4]] |
! |
阶乘 | y! |
从左到右 | 5! |
120 |
& |
按位与 | x & y |
从左到右 | 5 & 3 |
1 |
~ |
按位非 | ~x |
从右到左 | ~2 |
-3 |
| |
按位或 | x | y |
从左到右 | 5 | 3 |
7 |
^| |
按位异或 | x ^| y |
从左到右 | 5 ^| 2 |
7 |
<< |
左移 | x << y |
从左到右 | 4 << 1 |
8 |
>> |
算术右移 | x >> y |
从左到右 | 8 >> 1 |
4 |
>>> |
逻辑右移 | x >>> y |
从左到右 | -8 >>> 1 |
2147483644 |
and |
逻辑与 | x and y |
从左到右 | true and false |
false |
not |
逻辑非 | not y |
从右到左 | not true |
false |
or |
逻辑或 | x or y |
从左到右 | true or false |
true |
xor |
逻辑异或 | x xor y |
从左到右 | true xor true |
false |
= |
赋值 | x = y |
从右到左 | a = 5 |
5 |
? : |
条件表达式 | x ? y : z |
从右到左 | 15 > 100 ? 1 : -1 |
-1 |
?? |
空值合并 | x ?? y |
从左到右 | null ?? 2 |
2 |
?. |
可选链访问器 | obj?.prop |
从左到右 | obj={}; obj?.a |
undefined |
: |
范围 | x : y |
从右到左 | 1:4 |
[1,2,3,4] |
to, in |
单位转换 | x to y |
从左到右 | 2 inch to cm |
5.08 cm |
== |
相等 | x == y |
从左到右 | 2 == 4 - 2 |
true |
!= |
不相等 | x != y |
从左到右 | 2 != 3 |
true |
< |
小于 | x < y |
从左到右 | 2 < 3 |
true |
> |
大于 | x > y |
从左到右 | 2 > 3 |
false |
<= |
小于等于 | x <= y |
从左到右 | 4 <= 3 |
false |
>= |
大于等于 | x >= y |
从左到右 | 2 + 4 >= 6 |
true |
优先级 #
运算符的优先级从高到低如下
| 运算符 | Description |
|---|---|
(...)[...]{...} |
分组 矩阵 Object |
x(...)x[...]obj.prop: |
函数调用 矩阵索引 属性访问器 键/值分隔符 |
' |
矩阵转置 |
! |
阶乘 |
?? |
空值合并 |
^, .^ |
幂运算 |
+, -, ~, not |
一元加、一元减、按位非、逻辑非 |
% |
一元百分比 |
| 见下文 | 隐式乘法 |
*, /, .*, ./, %, mod |
乘法、除法、模运算 |
+, - |
加法、减法 |
: |
范围 |
to, in |
单位转换 |
<<, >>, >>> |
按位左移、算术右移、逻辑右移 |
==, !=, <, >, <=, >= |
关系运算 |
& |
按位与(懒惰求值) |
^| |
按位异或 |
| |
按位或(懒惰求值) |
and |
逻辑与(懒惰求值) |
xor |
逻辑异或 |
or |
逻辑或(懒惰求值) |
?, : |
条件表达式 |
= |
赋值 |
, |
参数和列分隔符 |
; |
行分隔符 |
\n, ; |
语句分隔符 |
在按位和逻辑运算符在逻辑上可行的情况下使用懒惰求值。在以下示例中,子表达式 x 甚至不会被计算,因为它不会影响最终结果
math.evaluate('false and x') // false, no matter what x equals
函数 #
函数通过输入其名称,后跟零个或多个括号括起来的参数来调用。所有可用的函数都在“函数”页面 Functions 上列出。
math.evaluate('sqrt(25)') // 5
math.evaluate('log(10000, 3 + 7)') // 4
math.evaluate('sin(pi / 4)') // 0.7071067811865475
可以通过“分配”表达式给一个或多个变量的函数调用来定义新函数。此类函数赋值是有限制的:它们只能在一行中定义。
const parser = math.parser()
parser.evaluate('f(x) = x ^ 2 - 5')
parser.evaluate('f(2)') // -1
parser.evaluate('f(3)') // 4
parser.evaluate('g(x, y) = x ^ y')
parser.evaluate('g(2, 3)') // 8
请注意,这些函数赋值不创建闭包;换句话说,mathjs 中的所有自由变量都是动态的
const parser = math.parser()
parser.evaluate('x = 7')
parser.evaluate('h(y) = x + y')
parser.evaluate('h(3)') // 10
parser.evaluate('x = 3')
parser.evaluate('h(3)') // 6, *not* 10
但是,可以传递函数作为参数
const parser = math.parser()
parser.evaluate('twice(func, x) = func(func(x))')
parser.evaluate('twice(square, 2)') // 16
parser.evaluate('f(x) = 3*x')
parser.evaluate('twice(f, 2)') // 18
// a simplistic "numerical derivative":
parser.evaluate('eps = 1e-10')
parser.evaluate('nd(f, x) = (f(x+eps) - func(x-eps))/(2*eps)')
parser.evaluate('nd(square,2)') // 4.000000330961484
Math.js 本身大量使用类型化函数,这些函数可确保输入正确,并在输入参数无效时抛出有意义的错误。可以在表达式解析器中创建 typed-function,如下所示
const parser = math.parser()
parser.evaluate('f = typed({"number": f(x) = x ^ 2 - 5})')
最后,如上所述,几乎所有数学运算符符号都有一个函数形式。此外,对于一些结合律运算符,相应的函数允许任意数量的参数。下表给出了完整的对应关系。
| 运算符表达式 | 等效函数表达式 |
|---|---|
a or b |
or(a,b) |
a xor b |
xor(a,b) |
a and b |
and(a,b) |
a \| b |
bitOr(a,b) |
a ^\| b |
bitXor(a,b) |
a & b |
bitAnd(a,b) |
a ?? b |
nullish(a,b) |
a == b |
equal(a,b) |
a != b |
unequal(a,b) |
a < b |
smaller(a,b) |
a > b |
larger(a,b) |
a <= b |
smallerEq(a,b) |
a << 3 |
leftShift(a,3) |
a >> 3 |
rightArithShift(a,3) |
a >>> 3 |
rightLogShift(a,3) |
u to cm |
to(u, cm) |
a + b + c + ... |
add(a,b,c,...) |
a - b |
subtract(a,b) |
a * b * c * ... |
multiply(a,b,c,...) |
A .* B |
dotMultiply(A,B) |
A ./ B |
dotDivide(A,B) |
a mod b |
mod(a,b) |
+a |
unaryPlus(a) |
-a |
unaryMinus(a) |
~a |
bitNot(a) |
not a |
not(a) |
a^b |
pow(a,b) |
A .^ B |
dotPow(A,B) |
a! |
factorial(a) |
A' |
ctranspose(A) |
请注意,math.js 偏好使用运算符形式,因为 simplify(参见 代数)会将任何函数形式转换为相应的运算符。
方法 #
某些数据类型具有方法,可以使用点表示法在解析器中使用,例如
const parser = math.parser()
parser.evaluate('a = 1 m') // Unit 1 m
parser.evaluate('a.toNumber("mm")') // 1000
或矩阵或数组上的方法
const parser = math.parser()
parser.evaluate('M = [4, 9, 25]') // Matrix [4, 9, 25]
parser.evaluate('M.map(sqrt)') // Matrix [2, 3, 5]
map 和 forEach #
可以使用 map 和 forEach 函数将回调函数应用于数组或矩阵的每个元素。
回调函数可以是函数、类型化函数、内联函数(仅在解析器中)或编译后的内联函数(仅在解析器中)。
回调可以具有以下输入
- value:数组或矩阵中的当前值。
- index:当前值的索引,表示为数字数组。
- array:正在迭代的数组或矩阵。
下面是两个函数的语法
map #
map 函数将函数应用于数组的每个元素,并返回一个包含结果的新数组。
const parser = math.parser()
// Define a square function
parser.evaluate('square(x) = x ^ 2')
// Apply the square function to each element of the array
parser.evaluate('result = map([1, 2, 3, 4], square)')
// result: [1, 4, 9, 16]
// Apply an inline function to each element of the array
parser.evaluate('result = map([1, 2, 3, 4], f(x) = x ^ 2)')
// result: [1, 4, 9, 16]
// Apply a compiled inline function to each element of the array
parser.evaluate('result = map([1, 2, 3, 4], x ^ 2)')
// result: [1, 4, 9, 16]
forEach #
forEach 函数将函数应用于数组或矩阵的每个元素,但不返回新数组。它对于执行副作用很有用。
// Define a function that prints each element
math.import({consoleLog: x => console.log(x)})
const parser = math.parser()
// Define a squareConsleLog function
parser.evaluate('squareConsoleLog(x) = consoleLog(x ^ 2)')
// Apply the squareConsleLog function to each element of the array
parser.evaluate('forEach([1, 2, 3, 4], squareConsleLog)')
// Prints: 1, 4, 9, 16
// Apply an inline function to each element of the array
parser.evaluate('forEach([1, 2, 3, 4], f(x) = consoleLog(x ^ 2))')
// Prints: 1, 4, 9, 16
// Apply a compiled inline function to each element of the array
parser.evaluate('forEach([1, 2, 3, 4], consoleLog(x ^ 2))')
// Prints: 1, 4, 9, 16
这些函数可用于对数组或矩阵执行逐元素操作。
常量和变量 #
Math.js 包含许多内置常量,如 pi 和 e。所有可用常量都在“常量”页面 Constants 上列出。
// use constants
math.evaluate('pi') // 3.141592653589793
math.evaluate('e ^ 2') // 7.3890560989306495
math.evaluate('log(e)') // 1
math.evaluate('e ^ (pi * i) + 1') // ~0 (Euler)
变量可以使用赋值运算符 = 定义,并像常量一样使用。
const parser = math.parser()
// define variables
parser.evaluate('a = 3.4') // 3.4
parser.evaluate('b = 5 / 2') // 2.5
// use variables
parser.evaluate('a * b') // 8.5
变量名必须
- 以“字母字符”开头,该字符是
- 拉丁字母(大写或小写)。ASCII:
a-z,A-Z - 下划线。ASCII:
_ - 美元符号。ASCII:
$ - 带重音符号的拉丁字母。Unicode:
\u00C0-\u02AF - 希腊字母。Unicode:
\u0370-\u03FF - 类字母字符。Unicode:
\u2100-\u214F - 数学字母数字符号。Unicode:
\u{1D400}-\u{1D7FF}排除无效码点
- 拉丁字母(大写或小写)。ASCII:
- 只包含字母字符(上方)和数字
0-9 - 不能是以下任何一个:
mod,to,in,and,xor,or,not,end。可以对其中一些进行赋值,但不推荐。
可以自定义允许的字母字符,有关更多信息,请参见 自定义支持的字符。
数据类型 #
表达式解析器支持布尔值、数字、复数、单位、字符串、矩阵和对象。
布尔值 #
布尔值 true 和 false 可用于表达式。
// use booleans
math.evaluate('true') // true
math.evaluate('false') // false
math.evaluate('(2 == 3) == false') // true
可以使用 number 和 boolean 以及 string 函数将布尔值转换为数字和字符串,反之亦然。
// convert booleans
math.evaluate('number(true)') // 1
math.evaluate('string(false)') // "false"
math.evaluate('boolean(1)') // true
math.evaluate('boolean("false")') // false
数字 #
math.js 中最重要和最基本的数据类型是数字。数字使用点作为小数点。数字可以用科学计数法输入。例如
// numbers in math.js
math.evaluate('2') // 2
math.evaluate('3.14') // 3.14
math.evaluate('1.4e3') // 1400
math.evaluate('22e-3') // 0.022
可以使用 number 和 string 函数将数字转换为字符串,反之亦然。
// convert a string into a number
math.evaluate('number("2.3")') // 2.3
math.evaluate('string(2.3)') // "2.3"
math.js 使用常规的 JavaScript 数字,它们是具有有限精度和有限范围的浮点数。有关限制的详细说明,请参见“数字”页面 Numbers。
math.evaluate('1e-325') // 0
math.evaluate('1e309') // Infinity
math.evaluate('-1e309') // -Infinity
在进行浮点数计算时,很容易产生舍入误差
// round-off error due to limited floating point precision
math.evaluate('0.1 + 0.2') // 0.30000000000000004
在输出结果时,可以使用 math.format 函数来隐藏这些舍入误差,以便用户查看。
const ans = math.evaluate('0.1 + 0.2') // 0.30000000000000004
math.format(ans, {precision: 14}) // "0.3"
数字可以表示为二进制、八进制和十六进制字面量
math.evaluate('0b11') // 3
math.evaluate('0o77') // 63
math.evaluate('0xff') // 255
可以使用字长后缀来更改非十进制字面量求值的行为
math.evaluate('0xffi8') // -1
math.evaluate('0xffffffffi32') // -1
math.evaluate('0xfffffffffi32') // SyntaxError: String "0xfffffffff" is out of range
非十进制数可以包含基数点
math.evaluate('0b1.1') // 1.5
math.evaluate('0o1.4') // 1.5
math.evaluate('0x1.8') // 1.5
可以使用 format 函数的 notation 选项将数字格式化为二进制、八进制和十六进制字符串。
math.evaluate('format(3, {notation: "bin"})') // '0b11'
math.evaluate('format(63, {notation: "oct"})') // '0o77'
math.evaluate('format(255, {notation: "hex"})') // '0xff'
math.evaluate('format(-1, {notation: "hex"})') // '-0x1'
math.evaluate('format(2.3, {notation: "hex"})') // '0x2.4cccccccccccc'
format 函数接受 wordSize 选项,以与非二进制表示法结合使用。
math.evaluate('format(-1, {notation: "hex", wordSize: 8})') // '0xffi8'
bin、oct 和 hex 函数是 format 函数的简写,其中 notation 设置相应。
math.evaluate('bin(-1)') // '-0b1'
math.evaluate('bin(-1, 8)') // '0b11111111i8'
大数 #
Math.js 支持大数进行任意精度计算。数字和Bignumber的优缺点已在“数字”页面 Numbers 中详细解释。
大数速度较慢但精度较高。大数计算仅由算术函数支持。
可以使用 bignumber 函数创建大数。
math.evaluate('bignumber(0.1) + bignumber(0.2)') // BigNumber, 0.3
表达式解析器的默认数字类型可以在实例化 math.js 时更改。表达式解析器默认将数字解析为 BigNumber。
// Configure the type of number: 'number' (default), 'BigNumber', or 'Fraction'
math.config({number: 'BigNumber'})
// all numbers are parsed as BigNumber
math.evaluate('0.1 + 0.2') // BigNumber, 0.3
可以使用 number 和 bignumber 函数将大数转换为数字,反之亦然。将大数转换为数字时,大数的高精度将丢失。当大数太大而无法表示为数字时,它将被初始化为 Infinity。
复数 #
可以使用虚数单位 i 来创建复数,定义为 i^2 = -1。复数具有实部和虚部,可以使用 re 和 im 函数检索。
const parser = math.parser()
// create complex numbers
parser.evaluate('a = 2 + 3i') // Complex, 2 + 3i
parser.evaluate('b = 4 - i') // Complex, 4 - i
// get real and imaginary part of a complex number
parser.evaluate('re(a)') // Number, 2
parser.evaluate('im(a)') // Number, 3
// calculations with complex numbers
parser.evaluate('a + b') // Complex, 6 + 2i
parser.evaluate('a * b') // Complex, 11 + 10i
parser.evaluate('i * i') // Number, -1
parser.evaluate('sqrt(-4)') // Complex, 2i
单位 #
math.js 支持单位。单位可用于加法、减法、乘法、除法和幂运算。单位也可以相互转换。有关所有可用单位的概述,请参见“单位”页面 Units。
可以使用 to 或 in 运算符将单位转换为其他单位。
// create a unit
math.evaluate('5.4 kg') // Unit, 5.4 kg
// convert a unit
math.evaluate('2 inch to cm') // Unit, 5.08 cm
math.evaluate('20 celsius in fahrenheit') // Unit, ~68 fahrenheit
math.evaluate('90 km/h to m/s') // Unit, 25 m / s
// convert a unit to a number
// A second parameter with the unit for the exported number must be provided
math.evaluate('number(5 cm, mm)') // Number, 50
// calculations with units
math.evaluate('0.5kg + 33g') // Unit, 0.533 kg
math.evaluate('3 inch + 2 cm') // Unit, 3.7874 inch
math.evaluate('3 inch + 2 cm') // Unit, 3.7874 inch
math.evaluate('12 seconds * 2') // Unit, 24 seconds
math.evaluate('sin(45 deg)') // Number, 0.7071067811865475
math.evaluate('9.81 m/s^2 * 5 s to mi/h') // Unit, 109.72172512527 mi / h
字符串 #
字符串用双引号 “ 或单引号 ‘ 括起来。字符串可以使用 concat 函数连接(不像在 JavaScript 中那样使用 + 添加它们)。可以通过索引检索或替换字符串的一部分。可以使用 number 函数将字符串转换为数字,并使用 string 函数将数字转换为字符串。
设置字符串中字符的值时,将返回已设置的字符。同样,当设置字符范围时,将返回该字符范围。
const parser = math.parser()
// create a string
parser.evaluate('"hello"') // String, "hello"
// string manipulation
parser.evaluate('a = concat("hello", " world")') // String, "hello world"
parser.evaluate('size(a)') // Matrix [11]
parser.evaluate('a[1:5]') // String, "hello"
parser.evaluate('a[1] = "H"') // String, "H"
parser.evaluate('a[7:12] = "there!"') // String, "there!"
parser.evaluate('a') // String, "Hello there!"
// string conversion
parser.evaluate('number("300")') // Number, 300
parser.evaluate('string(300)') // String, "300"
字符串可以在 evaluate 函数中使用,以便在表达式解析器中解析表达式。
math.evaluate('evaluate("2 + 3")') // 5
矩阵 #
可以通过在方括号中输入一系列值来创建矩阵,元素之间用逗号 , 分隔。像 [1, 2, 3] 这样的矩阵将创建一个向量,一个大小为 [3] 的一维矩阵。要创建多维矩阵,可以将矩阵嵌套在一起。为了更方便地创建二维矩阵,可以使用分号 ; 来分隔矩阵中的行。
// create a matrix
math.evaluate('[1, 2, 3]') // Matrix, size [3]
math.evaluate('[[1, 2, 3], [4, 5, 6]]') // Matrix, size [2, 3]
math.evaluate('[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]') // Matrix, size [2, 2, 2]
// create a two dimensional matrix
math.evaluate('[1, 2, 3; 4, 5, 6]') // Matrix, size [2, 3]
创建填充矩阵的另一种方法是使用 zeros、ones、identity 和 range 函数。
// initialize a matrix with ones or zeros
math.evaluate('zeros(3, 2)') // Matrix, [[0, 0], [0, 0], [0, 0]], size [3, 2]
math.evaluate('ones(3)') // Matrix, [1, 1, 1], size [3]
math.evaluate('5 * ones(2, 2)') // Matrix, [[5, 5], [5, 5]], size [2, 2]
// create an identity matrix
math.evaluate('identity(2)') // Matrix, [[1, 0], [0, 1]], size [2, 2]
// create a range
math.evaluate('1:4') // Matrix, [1, 2, 3, 4], size [4]
math.evaluate('0:2:10') // Matrix, [0, 2, 4, 6, 8, 10], size [6]
可以使用索引从矩阵中检索子集,并可以使用索引替换矩阵的子集。索引用方括号括起来,包含每个矩阵维度的数字或范围。范围可以将其开始和/或结束设置为未定义。当开始未定义时,范围将从 1 开始;当结束未定义时,范围将延伸到矩阵的末尾。
还有一个名为 end 的上下文变量,用于表示矩阵的末尾。此变量不能用于多个嵌套索引。在这种情况下,end 将解析为最内层矩阵的末尾。为了解决这个问题,需要将嵌套索引的解析拆分为两个独立的操作。
重要提示:矩阵索引和范围与 JavaScript 中的 math.js 索引不同:它们是从 1 开始的,并包含上限,与大多数数学应用程序类似。
重要提示:矩阵索引行为已在 mathjs v15 中更改,请参阅 将矩阵索引迁移到 mathjs v15 部分。
parser = math.parser()
// create matrices
parser.evaluate('a = [1, 2; 3, 4]') // Matrix, [[1, 2], [3, 4]]
parser.evaluate('b = zeros(2, 2)') // Matrix, [[0, 0], [0, 0]]
parser.evaluate('c = 5:9') // Matrix, [5, 6, 7, 8, 9]
// replace a subset in a matrix
parser.evaluate('b[1, 1:2] = [5, 6]') // Matrix, [[5, 6], [0, 0]]
parser.evaluate('b[2, :] = [7, 8]') // Matrix, [[5, 6], [7, 8]]
// perform a matrix calculation
parser.evaluate('d = a * b') // Matrix, [[19, 22], [43, 50]]
// retrieve a subset of a matrix
parser.evaluate('d[2, 1]') // 43
parser.evaluate('d[2, 1:end]') // Matrix, [43, 50]
parser.evaluate('c[end - 1 : -1 : 2]') // Matrix, [8, 7, 6]
将矩阵索引迁移到 mathjs v15 #
从 mathjs v15 开始,矩阵索引已更改为更加一致和可预测。在 v14 中,使用标量索引有时会降低结果的维度。在 v15 中,如果要保留维度,请使用数组、矩阵或范围索引。如果要获取标量值,请使用标量索引。
要保持旧的索引行为而无需进行任何代码更改,请使用配置选项 legacySubset。
math.config({ legacySubset: true })
要迁移您的代码,您必须将所有矩阵索引从旧的索引表示法更改为新的索引表示法。基本上:如果要输出数组,标量索引必须包装在数组括号中。这里有一些示例
parser = math.parser()
parser.evaluate('m = [1, 2, 3; 4, 5, 6]')
| v14 代码 | v15 等效代码 | 结果 |
|---|---|---|
m[1:2, 2:3] |
无需更改 | [[2, 3], [5, 6]] |
m[2, 2:3] |
m[[2], 2:3] |
[[5, 6]] |
m[1:2, 3] |
m[1:2, [3]] |
[[3], [6]] |
m[2, 3] |
无需更改 | 6 |
提示
如果要始终获取标量值,请使用标量索引。
如果要保留维度,请使用数组、矩阵或范围索引。
对象 #
math.js 中的对象与 JavaScript 和 Python 等语言中的对象相同。对象由花括号 {, } 括起来,包含一组以逗号分隔的键/值对。键和值之间用冒号 : 分隔。键可以是符号,如 prop,也可以是字符串,如 "prop"。
math.evaluate('{a: 2 + 1, b: 4}') // {a: 3, b: 4}
math.evaluate('{"a": 2 + 1, "b": 4}') // {a: 3, b: 4}
对象可以包含对象
math.evaluate('{a: 2, b: {c: 3, d: 4}}') // {a: 2, b: {c: 3, d: 4}}
可以使用点表示法或括号表示法检索或替换对象属性。与 JavaScript 不同,在设置属性值时,将返回整个对象,而不是属性值。
let scope = {
obj: {
prop: 42
}
}
// retrieve properties
math.evaluate('obj.prop', scope) // 42
math.evaluate('obj["prop"]', scope) // 42
// set properties (returns the whole object, not the property value!)
math.evaluate('obj.prop = 43', scope) // {prop: 43}
math.evaluate('obj["prop"] = 43', scope) // {prop: 43}
scope.obj // {prop: 43}
多行表达式 #
表达式可以包含多行,表达式可以跨越多行。行可以用换行符 \n 或分号 ; 分隔。后面跟分号的语句的输出将隐藏在输出中,空行将被忽略。输出作为 ResultSet 返回,每个可见语句都有一个条目。
// a multi-line expression
math.evaluate('1 * 3 \n 2 * 3 \n 3 * 3') // ResultSet, [3, 6, 9]
// semicolon statements are hidden from the output
math.evaluate('a=3; b=4; a + b \n a * b') // ResultSet, [7, 12]
// single expression spread over multiple lines
math.evaluate('a = 2 +\n 3') // 5
math.evaluate('[\n 1, 2;\n 3, 4\n]') // Matrix, [[1, 2], [3, 4]]
结果可以通过 ResultSet.entries 属性(它是一个 Array)从 ResultSet 中读取,或者通过调用 ResultSet.valueOf() 来获取,它返回结果数组。
隐式乘法 #
隐式乘法是指在没有使用 * 运算符的情况下,将两个符号、数字或括号内的分组表达式相乘。这种语法允许更自然地输入表达式。例如
math.evaluate('2 pi') // 6.283185307179586
math.evaluate('(1+2)(3+4)') // 21
当括号左侧有一个符号或访问器时,括号将被解析为函数调用,例如 sqrt(4) 或 obj.method(4)。在其他情况下,括号被解释为隐式乘法。
Math.js 总是先于显式乘法 * 对隐式乘法进行求值,因此表达式 x * y z 被解析为 x * (y * z)。Math.js 还赋予隐式乘法比除法更高的优先级,除非除法匹配模式 [unaryPrefixOp]?[number] / [number] [symbol] 或 [unaryPrefixOp]?[number] / [number] [left paren]。在这种特殊情况下,除法会先计算。
math.evaluate('20 kg / 4 kg') // 5 Evaluated as (20 kg) / (4 kg)
math.evaluate('20 / 4 kg') // 5 kg Evaluated as (20 / 4) kg
隐式乘法的行为可以通过以下运算符优先级规则来总结,从最高优先级到最低优先级
- 函数调用:
[symbol] [left paren] - 显式除法
/,当除法匹配以下模式时:[+-~]?[number] / [+-~]?[number] [symbol]或[number] / [number] [left paren] - 隐式乘法
- 所有其他除法
/和乘法*
隐式乘法是棘手的,因为表达式的求值方式可能出现歧义。经验表明,上述规则最符合用户在输入可能被不同解释的表达式时的意图。这些规则也可能在未来的主要版本中进行调整。请谨慎使用隐式乘法。如果您不喜欢隐式乘法带来的不确定性,请使用显式 * 运算符和括号来确保您的表达式按预期进行求值。
以下是更多使用隐式乘法的示例
| 表达式 | 求值为 | 结果 |
|---|---|---|
| (1 + 3) pi | (1 + 3) * pi | 12.566370614359172 |
| (4 - 1) 2 | (4 - 1) * 2 | 6 |
| 3 / 4 mm | (3 / 4) * mm | 0.75 mm |
| 2 + 3 i | 2 + (3 * i) | 2 + 3i |
| (1 + 2) (4 - 2) | (1 + 2) * (4 - 2) | 6 |
| sqrt(4) (1 + 2) | sqrt(4) * (1 + 2) | 6 |
| 8 pi / 2 pi | (8 * pi) / (2 * pi) | 4 |
| pi / 2 pi | pi / (2 * pi) | 0.5 |
| 1 / 2i | (1 / 2) * i | 0.5 i |
| 8.314 J / mol K | 8.314 J / (mol * K) | 8.314 J / (mol * K) |
注释 #
可以添加注释来解释或描述文本中的计算。注释以井号字符 # 开头,以行末结束。一行可以只包含注释,或者可以包含一个表达式后跟一个注释。
const parser = math.parser()
parser.evaluate('# define some variables')
parser.evaluate('width = 3') // 3
parser.evaluate('height = 4') // 4
parser.evaluate('width * height # calculate the area') // 12