UNPKG

6.36 kBJavaScriptView Raw
1/**
2 * Expressions can be evaluated in various ways:
3 *
4 * 1. using the function math.evaluate
5 * 2. using the function math.parse
6 * 3. using a parser. A parser contains functions evaluate and parse,
7 * and keeps a scope with assigned variables in memory
8 */
9
10// load math.js (using node.js)
11const math = require('..')
12
13// 1. using the function math.evaluate
14//
15// Function `evaluate` accepts a single expression or an array with
16// expressions as first argument, and has an optional second argument
17// containing a scope with variables and functions. The scope is a regular
18// JavaScript Object. The scope will be used to resolve symbols, and to write
19// assigned variables or function.
20console.log('1. USING FUNCTION MATH.EVAL')
21
22// evaluate expressions
23console.log('\nevaluate expressions')
24print(math.evaluate('sqrt(3^2 + 4^2)')) // 5
25print(math.evaluate('sqrt(-4)')) // 2i
26print(math.evaluate('2 inch to cm')) // 5.08 cm
27print(math.evaluate('cos(45 deg)')) // 0.70711
28
29// evaluate multiple expressions at once
30console.log('\nevaluate multiple expressions at once')
31print(math.evaluate([
32 'f = 3',
33 'g = 4',
34 'f * g'
35])) // [3, 4, 12]
36
37// provide a scope (just a regular JavaScript Object)
38console.log('\nevaluate expressions providing a scope with variables and functions')
39const scope = {
40 a: 3,
41 b: 4
42}
43
44// variables can be read from the scope
45print(math.evaluate('a * b', scope)) // 12
46
47// variable assignments are written to the scope
48print(math.evaluate('c = 2.3 + 4.5', scope)) // 6.8
49print(scope.c) // 6.8
50
51// scope can contain both variables and functions
52scope.hello = function (name) {
53 return 'hello, ' + name + '!'
54}
55print(math.evaluate('hello("hero")', scope)) // "hello, hero!"
56
57// define a function as an expression
58const f = math.evaluate('f(x) = x ^ a', scope)
59print(f(2)) // 8
60print(scope.f(2)) // 8
61
62// 2. using function math.parse
63//
64// Function `math.parse` parses expressions into a node tree. The syntax is
65// similar to function `math.evaluate`.
66// Function `parse` accepts a single expression or an array with
67// expressions as first argument. The function returns a node tree, which
68// then can be compiled against math, and then evaluated against an (optional
69// scope. This scope is a regular JavaScript Object. The scope will be used
70// to resolve symbols, and to write assigned variables or function.
71console.log('\n2. USING FUNCTION MATH.PARSE')
72
73// parse an expression
74console.log('\nparse an expression into a node tree')
75const node1 = math.parse('sqrt(3^2 + 4^2)')
76print(node1.toString()) // "sqrt((3 ^ 2) + (4 ^ 2))"
77
78// compile and evaluate the compiled code
79// you could also do this in two steps: node1.compile().evaluate()
80print(node1.evaluate()) // 5
81
82// provide a scope
83console.log('\nprovide a scope')
84const node2 = math.parse('x^a')
85const code2 = node2.compile()
86print(node2.toString()) // "x ^ a"
87const scope2 = {
88 x: 3,
89 a: 2
90}
91print(code2.evaluate(scope2)) // 9
92
93// change a value in the scope and re-evaluate the node
94scope.a = 3
95print(code2.evaluate(scope2)) // 27
96
97// 3. using function math.compile
98//
99// Function `math.compile` compiles expressions into a node tree. The syntax is
100// similar to function `math.evaluate`.
101// Function `compile` accepts a single expression or an array with
102// expressions as first argument, and returns an object with a function evaluate
103// to evaluate the compiled expression. On evaluation, an optional scope can
104// be provided. This scope will be used to resolve symbols, and to write
105// assigned variables or function.
106console.log('\n3. USING FUNCTION MATH.COMPILE')
107
108// parse an expression
109console.log('\ncompile an expression')
110const code3 = math.compile('sqrt(3^2 + 4^2)')
111
112// evaluate the compiled code
113print(code3.evaluate()) // 5
114
115// provide a scope for the variable assignment
116console.log('\nprovide a scope')
117const code4 = math.compile('a = a + 3')
118const scope3 = {
119 a: 7
120}
121code4.evaluate(scope3)
122print(scope3.a) // 10
123
124// 4. using a parser
125//
126// In addition to the static functions `math.evaluate` and `math.parse`, math.js
127// contains a parser with functions `evaluate` and `parse`, which automatically
128// keeps a scope with assigned variables in memory. The parser also contains
129// some convenience methods to get, set, and remove variables from memory.
130console.log('\n4. USING A PARSER')
131const parser = math.parser()
132
133// evaluate with parser
134console.log('\nevaluate expressions')
135print(parser.evaluate('sqrt(3^2 + 4^2)')) // 5
136print(parser.evaluate('sqrt(-4)')) // 2i
137print(parser.evaluate('2 inch to cm')) // 5.08 cm
138print(parser.evaluate('cos(45 deg)')) // 0.70710678118655
139
140// define variables and functions
141console.log('\ndefine variables and functions')
142print(parser.evaluate('x = 7 / 2')) // 3.5
143print(parser.evaluate('x + 3')) // 6.5
144print(parser.evaluate('f2(x, y) = x^y')) // f2(x, y)
145print(parser.evaluate('f2(2, 3)')) // 8
146
147// manipulate matrices
148// Note that matrix indexes in the expression parser are one-based with the
149// upper-bound included. On a JavaScript level however, math.js uses zero-based
150// indexes with an excluded upper-bound.
151console.log('\nmanipulate matrices')
152print(parser.evaluate('k = [1, 2; 3, 4]')) // [[1, 2], [3, 4]]
153print(parser.evaluate('l = zeros(2, 2)')) // [[0, 0], [0, 0]]
154print(parser.evaluate('l[1, 1:2] = [5, 6]')) // [5, 6]
155print(parser.evaluate('l')) // [[5, 6], [0, 0]]
156print(parser.evaluate('l[2, :] = [7, 8]')) // [7, 8]
157print(parser.evaluate('l')) // [[5, 6], [7, 8]]
158print(parser.evaluate('m = k * l')) // [[19, 22], [43, 50]]
159print(parser.evaluate('n = m[2, 1]')) // 43
160print(parser.evaluate('n = m[:, 1]')) // [[19], [43]]
161
162// get and set variables and functions
163console.log('\nget and set variables and function in the scope of the parser')
164const x = parser.get('x')
165console.log('x =', x) // x = 3.5
166const f2 = parser.get('f2')
167console.log('f2 =', math.format(f2)) // f2 = f2(x, y)
168const h = f2(3, 3)
169console.log('h =', h) // h = 27
170
171parser.set('i', 500)
172print(parser.evaluate('i / 2')) // 250
173parser.set('hello', function (name) {
174 return 'hello, ' + name + '!'
175})
176print(parser.evaluate('hello("hero")')) // "hello, hero!"
177
178// clear defined functions and variables
179parser.clear()
180
181/**
182 * Helper function to output a value in the console. Value will be formatted.
183 * @param {*} value
184 */
185function print (value) {
186 const precision = 14
187 console.log(math.format(value, precision))
188}