表达式树 #
通过 math.parse(expr) 解析表达式时,math.js 会生成一个表达式树并返回树的根节点。表达式树可用于分析、操作和求值表达式。
示例
const node = math.parse('sqrt(2 + x)')
在这种情况下,表达式 sqrt(2 + x) 被解析为
FunctionNode sqrt
|
OperatorNode +
/ \
ConstantNode 2 x SymbolNode
或者,可以通过手动创建节点来构建此表达式树
const node1 = new math.ConstantNode(2)
const node2 = new math.SymbolNode('x')
const node3 = new math.OperatorNode('+', 'add', [node1, node2])
const node4 = new math.FunctionNode('sqrt', [node3])
生成的根节点为 node4 的表达式树等于通过 math.parse('sqrt(2 + x)') 生成的表达式树。
API #
方法 #
所有节点都具有以下方法
-
clone() : Node创建节点的浅拷贝。仅克隆节点本身,而不克隆其子节点。
-
cloneDeep() : Node创建节点的深拷贝。节点及其所有子节点都将被递归克隆。
-
compile() : Object将表达式编译为优化的 JavaScript 代码。
compile返回一个具有evaluate([scope])函数的对象,用于求值。示例const node = math.parse('2 + x') // returns the root Node of an expression tree const code = node.compile() // returns {evaluate: function (scope) {...}} const evaluate = code.evaluate({x: 3}) // returns 5 -
evaluate([scope]) : Object编译并求值表达式,这等同于执行
node.compile().evaluate(scope)。示例const node = math.parse('2 + x') // returns the root Node of an expression tree const evaluate = node.evaluate({x: 3}) // returns 5 -
equals(other: Node) : boolean测试此节点是否等于另一个节点。执行两个节点值的深度比较。
-
filter(callback: function) : Node[]递归地过滤表达式树中的节点。
callback函数将作为callback(node: Node, path: string, parent: Node) : boolean调用,用于树中的每个节点,并且必须返回一个布尔值。filter函数返回一个数组,其中包含测试返回 true 的节点。path参数是一个包含相对 JSON Path 的字符串。示例
const node = math.parse('x^2 + x/4 + 3*y') const filtered = node.filter(function (node) { return node.isSymbolNode && node.name === 'x' }) // returns an array with two entries: two SymbolNodes 'x' -
forEach(callback: function) : void对当前节点的每个子节点执行回调函数。
callback函数将作为callback(child: Node, path: string, parent: Node): void调用。path参数是一个包含相对 JSON Path 的字符串。另请参阅
traverse,它是forEach的递归版本。示例
const node = math.parse('3 * x + 2') node.forEach(function (node, path, parent) { switch (node.type) { case 'OperatorNode': console.log(node.type, node.op) break case 'ConstantNode': console.log(node.type, node.value) break case 'SymbolNode': console.log(node.type, node.name) break default: console.log(node.type) } }) // outputs: // OperatorNode * // ConstantNode 2 -
map(callback: function) : Node[]转换节点。创建一个新节点,其子节点是通过对原始节点中的每个子节点调用提供的回调函数的结果。
callback函数将作为callback(child: Node, path: string, parent: Node)调用,并且必须返回一个 Node。path参数是一个包含相对 JSON Path 的字符串。另请参阅
transform,它是map的递归版本。 -
toHTML(options: object): string获取已解析表达式的 HTML 表示。示例
const node = math.parse('sqrt(2/3)') node.toHTML() // returns // <span class="math-function">sqrt</span> // <span class="math-paranthesis math-round-parenthesis">(</span> // <span class="math-number">2</span> // <span class="math-operator math-binary-operator math-explicit-binary-operator">/</span> // <span class="math-number">3</span> // <span class="math-paranthesis math-round-parenthesis">)</span>有关可用 HTML 类的信息,请参阅 HTML Classes。有关选项的信息,请参阅 Customization。
-
toString(options: object) : string获取已解析表达式的字符串表示。这与原始输入不完全相同。示例
const node = math.parse('3+4*2') node.toString() // returns '3 + (4 * 2)'有关选项的信息,请参阅 Customization。
-
toTex(options: object): string获取表达式的 LaTeX 表示。示例
const node = math.parse('sqrt(2/3)') node.toTex() // returns '\sqrt{\frac{2}{3}}'有关选项的信息,请参阅 Customization。
-
transform(callback: function)通过转换函数递归地转换表达式树。类似于
Array.map,但会递归地在表达式树中的所有节点上执行。回调函数是一个接受节点并返回节点替换项或原始节点的映射函数。callback函数将作为callback(node: Node, path: string, parent: Node)调用,用于树中的每个节点,并且必须返回一个Node。path参数是一个包含相对 JSON Path 的字符串。当节点被回调函数替换时,转换函数将停止迭代,它不会迭代被替换的节点。
例如,要将类型为
SymbolNode且名称为 'x' 的所有节点替换为值为3的ConstantNodeconst node = math.parse('x^2 + 5*x') const transformed = node.transform(function (node, path, parent) { if (node.isSymbolNode && node.name === 'x') { return new math.ConstantNode(3) } else { return node } }) transformed.toString() // returns '3 ^ 2 + 5 * 3' -
traverse(callback: function): void递归遍历节点树中的所有节点。为当前节点及其每个子节点执行给定的回调函数。类似于
Array.forEach,但它是递归的。回调函数是一个接受节点并且不返回任何内容的映射函数。callback函数将作为callback(node: Node, path: string, parent: Node)调用,用于树中的每个节点。path参数是一个包含相对 JSON Path 的字符串。示例const node = math.parse('3 * x + 2') node.traverse(function (node, path, parent) { switch (node.type) { case 'OperatorNode': console.log(node.type, node.op) break case 'ConstantNode': console.log(node.type, node.value) break case 'SymbolNode': console.log(node.type, node.name) break default: console.log(node.type) } }) // outputs: // OperatorNode + // OperatorNode * // ConstantNode 3 // SymbolNode x // ConstantNode 2
属性 #
每个 Node 都具有以下属性
-
comment: string一个字符串,用于保存表达式中的注释(如果存在),否则为空字符串。注释可以附加到表达式的根节点或
BlockNode的每个子节点。 -
isNode: true在 Nodes 上定义为
true。此外,每种类型的节点都会添加自己的标志,例如SymbolNode具有isSymbolNode: true属性。 -
type: string节点的类型,例如
SymbolNode的情况下的'SymbolNode'。
节点 #
math.js 具有以下类型的节点。所有节点都可以在命名空间 math 中访问。
AccessorNode #
构造
new AccessorNode(object: Node, index: IndexNode)
new AccessorNode(object: Node, index: IndexNode, optionalChaining: boolean)
可以提供一个可选属性 optionalChaining,用于指示访问器是使用可选链 a?.b 还是使用方括号表示法 a?.["b"] 编写的。默认值为 false。如果给定的对象未定义或为 null,则强制求值为 undefined。
属性
object: Nodeindex: IndexNodename: string(只读) 函数或方法名称。当未定义时返回空字符串。optionalChaining: boolean
示例
const node1 = math.parse('a[3]')
const object = new math.SymbolNode('a')
const constant3 = new math.ConstantNode(3)
const index = new math.IndexNode([constant3])
const node2 = new math.AccessorNode(object, index)
ArrayNode #
构造
new ArrayNode(items: Node[])
属性
items: Node[]
示例
const node1 = math.parse('[1, 2, 3]')
const one = new math.ConstantNode(1)
const two = new math.ConstantNode(2)
const three = new math.ConstantNode(3)
const node2 = new math.ArrayNode([one, two, three])
AssignmentNode #
构造
new AssignmentNode(object: SymbolNode, value: Node)
new AssignmentNode(object: SymbolNode | AccessorNode, index: IndexNode, value: Node)
属性
object: SymbolNode | AccessorNodeindex: IndexNode | nullvalue: Nodename: string(只读) 函数或方法名称。当未定义时返回空字符串。
示例
const node1 = math.parse('a = 3')
const object = new math.SymbolNode('a')
const value = new math.ConstantNode(3)
const node2 = new math.AssignmentNode(object, value)
BlockNode #
当解析多行表达式(如 a=2;b=3 或 a=2\nb=3)时,会创建 BlockNode。求值 BlockNode 会返回一个 ResultSet。结果可以通过 ResultSet.entries 或 ResultSet.valueOf() 检索,其中包含一个 Array,其中的元素是可见行的(即不以分号结尾的行)的结果。
构造
block = new BlockNode(Array.<{node: Node} | {node: Node, visible: boolean}>)
属性
blocks: Array.<{node: Node, visible: boolean}>
示例
const block1 = math.parse('a=1; b=2; c=3')
const a = new math.SymbolNode('a')
const one = new math.ConstantNode(1)
const ass1 = new math.AssignmentNode(a, one)
const b = new math.SymbolNode('b')
const two = new math.ConstantNode(2)
const ass2 = new math.AssignmentNode(b, two)
const c = new math.SymbolNode('c')
const three = new math.ConstantNode(3)
const ass3 = new math.AssignmentNode(c, three)
const block2 = new BlockNode([
{node: ass1, visible: false},
{node: ass2, visible: false},
{node: ass3, visible: true}
])
ConditionalNode #
构造
new ConditionalNode(condition: Node, trueExpr: Node, falseExpr: Node)
属性
condition: NodetrueExpr: NodefalseExpr: Node
示例
const node1 = math.parse('a > 0 ? a : -a')
const a = new math.SymbolNode('a')
const zero = new math.ConstantNode(0)
const condition = new math.OperatorNode('>', 'larger', [a, zero])
const trueExpr = a
const falseExpr = new math.OperatorNode('-', 'unaryMinus', [a])
const node2 = new math.ConditionalNode(condition, trueExpr, falseExpr)
ConstantNode #
构造
new ConstantNode(value: *)
属性
value: *
示例
const node1 = math.parse('2.4')
const node2 = new math.ConstantNode(2.4)
const node3 = new math.ConstantNode('foo')
FunctionAssignmentNode #
构造
new FunctionAssignmentNode(name: string, params: string[], expr: Node)
属性
name: stringparams: string[]expr: Node
示例
const node1 = math.parse('f(x) = x^2')
const x = new math.SymbolNode('x')
const two = new math.ConstantNode(2)
const expr = new math.OperatorNode('^', 'pow', [x, 2])
const node2 = new math.FunctionAssignmentNode('f', ['x'], expr)
FunctionNode #
构造
new FunctionNode(fn: Node | string, args: Node[])
属性
fn: Node | string(只读) 要调用的对象或函数名称。args: Node[]
静态函数
FunctionNode.onUndefinedFunction(name: string)。当求值未定义的函数时,会调用此函数。默认情况下,该函数会抛出异常“Undefined function x”。可以重写此函数来自定义行为。另请参阅SymbolNode.onUndefinedSymbol。
示例
const node1 = math.parse('sqrt(4)')
const four = new math.ConstantNode(4)
const node3 = new math.FunctionNode(new SymbolNode('sqrt'), [four])
IndexNode #
构造
new IndexNode(dimensions: Node[])
new IndexNode(dimensions: Node[], dotNotation: boolean)
每个维度可以是一个单一值、一个范围或一个属性。索引的值从一开始,包括范围的结束。
可以提供一个可选属性 dotNotation,用于描述索引是使用点表示法(如 a.b)还是使用方括号表示法(如 a["b"])编写的。默认值为 false。此信息用于字符串化 IndexNode。
属性
dimensions: Node[]dotNotation: boolean
示例
const node1 = math.parse('A[1:3, 2]')
const A = new math.SymbolNode('A')
const one = new math.ConstantNode(1)
const two = new math.ConstantNode(2)
const three = new math.ConstantNode(3)
const range = new math.RangeNode(one, three)
const index = new math.IndexNode([range, two])
const node2 = new math.AccessorNode(A, index)
ObjectNode #
构造
new ObjectNode(properties: Object.<string, Node>)
属性
properties: Object.<string, Node>
示例
const node1 = math.parse('{a: 1, b: 2, c: 3}')
const a = new math.ConstantNode(1)
const b = new math.ConstantNode(2)
const c = new math.ConstantNode(3)
const node2 = new math.ObjectNode({a: a, b: b, c: c})
OperatorNode #
构造
new OperatorNode(op: string, fn: string, args: Node[], implicit: boolean = false)
附加方法
-
isUnary() : boolean当
OperatorNode包含正好一个参数时(例如,一元减法),返回 true。const a = new math.ConstantNode(2) const b = new math.OperatorNode('-', 'unaryMinus', [a]) b.isUnary() // true -
isBinary() : boolean当
OperatorNode包含正好两个参数时(例如,大多数常规运算符),返回 true。const a = new math.ConstantNode(2) const b = new math.ConstantNode(3) const c = new math.OperatorNode('+', 'add', [a, b]) c.isBinary() // true
属性
op: stringfn: stringargs: Node[]implicit: boolean在隐式乘法时为 true,否则为 false。
示例
const node1 = math.parse('2.3 + 5')
const a = new math.ConstantNode(2.3)
const b = new math.ConstantNode(5)
const node2 = new math.OperatorNode('+', 'add', [a, b])
ParenthesisNode #
构造
new ParenthesisNode(content: Node)
属性
content: Node
示例
const node1 = math.parse('(1)')
const a = new math.ConstantNode(1)
const node2 = new math.ParenthesisNode(a)
RangeNode #
构造
new RangeNode(start: Node, end: Node [, step: Node])
属性
start: Nodeend: Nodestep: Node | null
示例
const node1 = math.parse('1:10')
const node2 = math.parse('0:2:10')
const zero = new math.ConstantNode(0)
const one = new math.ConstantNode(1)
const two = new math.ConstantNode(2)
const ten = new math.ConstantNode(10)
const node3 = new math.RangeNode(one, ten)
const node4 = new math.RangeNode(zero, ten, two)
RelationalNode #
构造
new RelationalNode(conditionals: string[], params: Node[])
conditionals 是一个字符串数组,每个字符串可以是 'smaller'、'larger'、'smallerEq'、'largerEq'、'equal' 或 'unequal'。 conditionals 数组必须比 params 少一个元素。
属性
conditionals: string[]params: Node[]
一个 RelationalNode 高效地表示带有两个或多个比较运算符的链式条件表达式,例如 10 < x <= 50。该表达式等同于 10 < x and x <= 50,不同之处在于 x 只计算一次,并且一旦任何条件测试为 false,计算就会停止(“短路”)。可以进行链式比较的运算符是 <、>、<=、>=、== 和 !=。为了向后兼容,如果只存在单个条件(例如 x > 2),math.parse 将返回一个 OperatorNode。
示例
const ten = new math.ConstantNode(10)
const x = new math.SymbolNode('x')
const fifty = new math.ConstantNode(50)
const node1 = new math.RelationalNode(['smaller', 'smallerEq'], [ten, x, fifty])
const node2 = math.parse('10 < x <= 50')
SymbolNode #
构造
new SymbolNode(name: string)
属性
name: string
静态函数
SymbolNode.onUndefinedSymbol(name: string)。当求值未定义的符号时,会调用此函数。默认情况下,该函数会抛出异常“Undefined symbol x”。可以重写此函数来自定义行为。另请参阅FunctionNode.onUndefinedFunction。
示例
const node = math.parse('x')
const x = new math.SymbolNode('x')