189 lines
6.2 KiB
JavaScript
189 lines
6.2 KiB
JavaScript
/**
|
|
* Expressions can be evaluated in various ways:
|
|
*
|
|
* 1. using the function math.evaluate
|
|
* 2. using the function math.parse
|
|
* 3. using a parser. A parser contains functions evaluate and parse,
|
|
* and keeps a scope with assigned variables in memory
|
|
*/
|
|
|
|
// load math.js (using node.js)
|
|
const math = require('..')
|
|
|
|
// 1. using the function math.evaluate
|
|
//
|
|
// Function `evaluate` accepts a single expression or an array with
|
|
// expressions as first argument, and has an optional second argument
|
|
// containing a scope with variables and functions. The scope is a regular
|
|
// JavaScript Object. The scope will be used to resolve symbols, and to write
|
|
// assigned variables or function.
|
|
console.log('1. USING FUNCTION MATH.EVAL')
|
|
|
|
// evaluate expressions
|
|
console.log('\nevaluate expressions')
|
|
print(math.evaluate('sqrt(3^2 + 4^2)')) // 5
|
|
print(math.evaluate('sqrt(-4)')) // 2i
|
|
print(math.evaluate('2 inch to cm')) // 5.08 cm
|
|
print(math.evaluate('cos(45 deg)')) // 0.70711
|
|
|
|
// evaluate multiple expressions at once
|
|
console.log('\nevaluate multiple expressions at once')
|
|
print(math.evaluate([
|
|
'f = 3',
|
|
'g = 4',
|
|
'f * g'
|
|
])) // [3, 4, 12]
|
|
|
|
// provide a scope (just a regular JavaScript Object)
|
|
console.log('\nevaluate expressions providing a scope with variables and functions')
|
|
const scope = {
|
|
a: 3,
|
|
b: 4
|
|
}
|
|
|
|
// variables can be read from the scope
|
|
print(math.evaluate('a * b', scope)) // 12
|
|
|
|
// variable assignments are written to the scope
|
|
print(math.evaluate('c = 2.3 + 4.5', scope)) // 6.8
|
|
print(scope.c) // 6.8
|
|
|
|
// scope can contain both variables and functions
|
|
scope.hello = function (name) {
|
|
return 'hello, ' + name + '!'
|
|
}
|
|
print(math.evaluate('hello("hero")', scope)) // "hello, hero!"
|
|
|
|
// define a function as an expression
|
|
const f = math.evaluate('f(x) = x ^ a', scope)
|
|
print(f(2)) // 8
|
|
print(scope.f(2)) // 8
|
|
|
|
// 2. using function math.parse
|
|
//
|
|
// Function `math.parse` parses expressions into a node tree. The syntax is
|
|
// similar to function `math.evaluate`.
|
|
// Function `parse` accepts a single expression or an array with
|
|
// expressions as first argument. The function returns a node tree, which
|
|
// then can be compiled against math, and then evaluated against an (optional
|
|
// scope. This scope is a regular JavaScript Object. The scope will be used
|
|
// to resolve symbols, and to write assigned variables or function.
|
|
console.log('\n2. USING FUNCTION MATH.PARSE')
|
|
|
|
// parse an expression
|
|
console.log('\nparse an expression into a node tree')
|
|
const node1 = math.parse('sqrt(3^2 + 4^2)')
|
|
print(node1.toString()) // "sqrt((3 ^ 2) + (4 ^ 2))"
|
|
|
|
// compile and evaluate the compiled code
|
|
// you could also do this in two steps: node1.compile().evaluate()
|
|
print(node1.evaluate()) // 5
|
|
|
|
// provide a scope
|
|
console.log('\nprovide a scope')
|
|
const node2 = math.parse('x^a')
|
|
const code2 = node2.compile()
|
|
print(node2.toString()) // "x ^ a"
|
|
const scope2 = {
|
|
x: 3,
|
|
a: 2
|
|
}
|
|
print(code2.evaluate(scope2)) // 9
|
|
|
|
// change a value in the scope and re-evaluate the node
|
|
scope2.a = 3
|
|
print(code2.evaluate(scope2)) // 27
|
|
|
|
// 3. using function math.compile
|
|
//
|
|
// Function `math.compile` compiles expressions into a node tree. The syntax is
|
|
// similar to function `math.evaluate`.
|
|
// Function `compile` accepts a single expression or an array with
|
|
// expressions as first argument, and returns an object with a function evaluate
|
|
// to evaluate the compiled expression. On evaluation, an optional scope can
|
|
// be provided. This scope will be used to resolve symbols, and to write
|
|
// assigned variables or function.
|
|
console.log('\n3. USING FUNCTION MATH.COMPILE')
|
|
|
|
// parse an expression
|
|
console.log('\ncompile an expression')
|
|
const code3 = math.compile('sqrt(3^2 + 4^2)')
|
|
|
|
// evaluate the compiled code
|
|
print(code3.evaluate()) // 5
|
|
|
|
// provide a scope for the variable assignment
|
|
console.log('\nprovide a scope')
|
|
const code4 = math.compile('a = a + 3')
|
|
const scope3 = {
|
|
a: 7
|
|
}
|
|
code4.evaluate(scope3)
|
|
print(scope3.a) // 10
|
|
|
|
// 4. using a parser
|
|
//
|
|
// In addition to the static functions `math.evaluate` and `math.parse`, math.js
|
|
// contains a parser with functions `evaluate` and `parse`, which automatically
|
|
// keeps a scope with assigned variables in memory. The parser also contains
|
|
// some convenience methods to get, set, and remove variables from memory.
|
|
console.log('\n4. USING A PARSER')
|
|
const parser = math.parser()
|
|
|
|
// evaluate with parser
|
|
console.log('\nevaluate expressions')
|
|
print(parser.evaluate('sqrt(3^2 + 4^2)')) // 5
|
|
print(parser.evaluate('sqrt(-4)')) // 2i
|
|
print(parser.evaluate('2 inch to cm')) // 5.08 cm
|
|
print(parser.evaluate('cos(45 deg)')) // 0.70710678118655
|
|
|
|
// define variables and functions
|
|
console.log('\ndefine variables and functions')
|
|
print(parser.evaluate('x = 7 / 2')) // 3.5
|
|
print(parser.evaluate('x + 3')) // 6.5
|
|
print(parser.evaluate('f2(x, y) = x^y')) // f2(x, y)
|
|
print(parser.evaluate('f2(2, 3)')) // 8
|
|
|
|
// manipulate matrices
|
|
// Note that matrix indexes in the expression parser are one-based with the
|
|
// upper-bound included. On a JavaScript level however, math.js uses zero-based
|
|
// indexes with an excluded upper-bound.
|
|
console.log('\nmanipulate matrices')
|
|
print(parser.evaluate('k = [1, 2; 3, 4]')) // [[1, 2], [3, 4]]
|
|
print(parser.evaluate('l = zeros(2, 2)')) // [[0, 0], [0, 0]]
|
|
print(parser.evaluate('l[1, 1:2] = [5, 6]')) // [5, 6]
|
|
print(parser.evaluate('l')) // [[5, 6], [0, 0]]
|
|
print(parser.evaluate('l[2, :] = [7, 8]')) // [7, 8]
|
|
print(parser.evaluate('l')) // [[5, 6], [7, 8]]
|
|
print(parser.evaluate('m = k * l')) // [[19, 22], [43, 50]]
|
|
print(parser.evaluate('n = m[2, 1]')) // 43
|
|
print(parser.evaluate('n = m[:, 1]')) // [[19], [43]]
|
|
|
|
// get and set variables and functions
|
|
console.log('\nget and set variables and function in the scope of the parser')
|
|
const x = parser.get('x')
|
|
console.log('x =', x) // x = 3.5
|
|
const f2 = parser.get('f2')
|
|
console.log('f2 =', math.format(f2)) // f2 = f2(x, y)
|
|
const h = f2(3, 3)
|
|
console.log('h =', h) // h = 27
|
|
|
|
parser.set('i', 500)
|
|
print(parser.evaluate('i / 2')) // 250
|
|
parser.set('hello', function (name) {
|
|
return 'hello, ' + name + '!'
|
|
})
|
|
print(parser.evaluate('hello("hero")')) // "hello, hero!"
|
|
|
|
// clear defined functions and variables
|
|
parser.clear()
|
|
|
|
/**
|
|
* Helper function to output a value in the console. Value will be formatted.
|
|
* @param {*} value
|
|
*/
|
|
function print (value) {
|
|
const precision = 14
|
|
console.log(math.format(value, precision))
|
|
}
|