expressions.js (6357B)
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) 11 const 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. 20 console.log('1. USING FUNCTION MATH.EVAL') 21 22 // evaluate expressions 23 console.log('\nevaluate expressions') 24 print(math.evaluate('sqrt(3^2 + 4^2)')) // 5 25 print(math.evaluate('sqrt(-4)')) // 2i 26 print(math.evaluate('2 inch to cm')) // 5.08 cm 27 print(math.evaluate('cos(45 deg)')) // 0.70711 28 29 // evaluate multiple expressions at once 30 console.log('\nevaluate multiple expressions at once') 31 print(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) 38 console.log('\nevaluate expressions providing a scope with variables and functions') 39 const scope = { 40 a: 3, 41 b: 4 42 } 43 44 // variables can be read from the scope 45 print(math.evaluate('a * b', scope)) // 12 46 47 // variable assignments are written to the scope 48 print(math.evaluate('c = 2.3 + 4.5', scope)) // 6.8 49 print(scope.c) // 6.8 50 51 // scope can contain both variables and functions 52 scope.hello = function (name) { 53 return 'hello, ' + name + '!' 54 } 55 print(math.evaluate('hello("hero")', scope)) // "hello, hero!" 56 57 // define a function as an expression 58 const f = math.evaluate('f(x) = x ^ a', scope) 59 print(f(2)) // 8 60 print(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. 71 console.log('\n2. USING FUNCTION MATH.PARSE') 72 73 // parse an expression 74 console.log('\nparse an expression into a node tree') 75 const node1 = math.parse('sqrt(3^2 + 4^2)') 76 print(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() 80 print(node1.evaluate()) // 5 81 82 // provide a scope 83 console.log('\nprovide a scope') 84 const node2 = math.parse('x^a') 85 const code2 = node2.compile() 86 print(node2.toString()) // "x ^ a" 87 const scope2 = { 88 x: 3, 89 a: 2 90 } 91 print(code2.evaluate(scope2)) // 9 92 93 // change a value in the scope and re-evaluate the node 94 scope2.a = 3 95 print(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. 106 console.log('\n3. USING FUNCTION MATH.COMPILE') 107 108 // parse an expression 109 console.log('\ncompile an expression') 110 const code3 = math.compile('sqrt(3^2 + 4^2)') 111 112 // evaluate the compiled code 113 print(code3.evaluate()) // 5 114 115 // provide a scope for the variable assignment 116 console.log('\nprovide a scope') 117 const code4 = math.compile('a = a + 3') 118 const scope3 = { 119 a: 7 120 } 121 code4.evaluate(scope3) 122 print(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. 130 console.log('\n4. USING A PARSER') 131 const parser = math.parser() 132 133 // evaluate with parser 134 console.log('\nevaluate expressions') 135 print(parser.evaluate('sqrt(3^2 + 4^2)')) // 5 136 print(parser.evaluate('sqrt(-4)')) // 2i 137 print(parser.evaluate('2 inch to cm')) // 5.08 cm 138 print(parser.evaluate('cos(45 deg)')) // 0.70710678118655 139 140 // define variables and functions 141 console.log('\ndefine variables and functions') 142 print(parser.evaluate('x = 7 / 2')) // 3.5 143 print(parser.evaluate('x + 3')) // 6.5 144 print(parser.evaluate('f2(x, y) = x^y')) // f2(x, y) 145 print(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. 151 console.log('\nmanipulate matrices') 152 print(parser.evaluate('k = [1, 2; 3, 4]')) // [[1, 2], [3, 4]] 153 print(parser.evaluate('l = zeros(2, 2)')) // [[0, 0], [0, 0]] 154 print(parser.evaluate('l[1, 1:2] = [5, 6]')) // [5, 6] 155 print(parser.evaluate('l')) // [[5, 6], [0, 0]] 156 print(parser.evaluate('l[2, :] = [7, 8]')) // [7, 8] 157 print(parser.evaluate('l')) // [[5, 6], [7, 8]] 158 print(parser.evaluate('m = k * l')) // [[19, 22], [43, 50]] 159 print(parser.evaluate('n = m[2, 1]')) // 43 160 print(parser.evaluate('n = m[:, 1]')) // [[19], [43]] 161 162 // get and set variables and functions 163 console.log('\nget and set variables and function in the scope of the parser') 164 const x = parser.get('x') 165 console.log('x =', x) // x = 3.5 166 const f2 = parser.get('f2') 167 console.log('f2 =', math.format(f2)) // f2 = f2(x, y) 168 const h = f2(3, 3) 169 console.log('h =', h) // h = 27 170 171 parser.set('i', 500) 172 print(parser.evaluate('i / 2')) // 250 173 parser.set('hello', function (name) { 174 return 'hello, ' + name + '!' 175 }) 176 print(parser.evaluate('hello("hero")')) // "hello, hero!" 177 178 // clear defined functions and variables 179 parser.clear() 180 181 /** 182 * Helper function to output a value in the console. Value will be formatted. 183 * @param {*} value 184 */ 185 function print (value) { 186 const precision = 14 187 console.log(math.format(value, precision)) 188 }