Numeric Evaluation
To obtain an exact numeric evaluation of an expression use expr.evaluate().
To obtain a numeric approximation use expr.N().
Parse + Numeric Free Function
For the common "parse then numeric approximation" flow, use the N() free
function:
The N() free function accepts either a LaTeX string or an Expression.
It uses a shared ComputeEngine instance created on first call.
Exact Evaluation
An evaluation with expr.evaluate() preserves exact values.
Exact values are:
| Type | Examples |
|---|---|
| Integers | 42, -1234 |
| Rationals | \nicefrac{3}{4}, -\nicefrac{11}{7} |
| Square Roots of Integers | \sqrt{2}, -3\sqrt{5} |
| Constants | e (ExponentialE), \pi (Pi) |
Numeric Approximation
To force the evaluation of an expression to be a numeric approximation, use expr.N().
When using expr.evaluate(), if one of the arguments is not an exact value
the expression is automatically evaluated as a numeric approximation.
Angular Units
When a trigonometric function is given a unitless value, the Compute Engine
interprets it using the current angular unit. Set it with ce.angularUnit
(default: "rad").
Valid values: "rad", "deg", "grad", "turn".
JavaScript Interoperability
The result of expr.evaluate() and expr.N() is a expression.
The numericValue property of this expression is either a machine number
(a JavaScript number), a NumericValue object or null if the expression
is not a number.
While a NumericValue object can represent arbitrary precision numbers, for
use with JavaScript, a reduced precision approximation can be accessed using
the re (for the real part of the number) and im (for the imaginary part)
properties.
const expr = parse('1/3 + 1/4');
console.log(expr.N().re);
// ➔ 0.5833333333333334
Another way to obtain a JavaScript compatible representation of an expression
is to use the valueOf() method of the expression.
const expr = parse('1/3 + 1/4');
console.log(expr.N().valueOf());
// ➔ 0.5833333333333334
The valueOf() method of a expression can be used in JavaScript
expressions.
Unlike the .re property, valueOf() can also return a boolean or a
string, depending on the value of the expression.
To get an Expression number literal from a JavaScript number, use ce.expr() or ce.number().
Numeric Precision
The number of significant digits used in numeric calculations is controlled
by the ce.precision property of the ComputeEngine instance.
The default precision is 21.
To set the precision to the default value, use ce.precision = "auto".
To request a specific precision for a single evaluation, use the N
function with a precision argument: ["N", expr, digits].
If the requested precision is greater than ce.precision, the working precision
is raised to match and kept raised (display precision is global). If it is at
or below ce.precision, the result is rounded to that many significant digits
without changing the working precision.
Machine Precision
If the precision is 15 or less, the Compute Engine uses a 64-bit binary floating point format for its internal calculations.
This format is implemented in hardware and well suited to do fast computations.
It uses a fixed amount of memory and represents significant digits in base-2 with
about 15 digits of precision and with a minimum value of \pm5\times 10^{-324} and a maximum value of \pm1.7976931348623157\times 10^{+308}
To change the precision to machine precision, use
ce.precision = "machine".
With this precision, some calculations that have a value very close to 0
may return 0 and some calculations that have a value greater than the
maximum value representable by a machine number may return \pm\infty.
Some numeric evaluations using machine numbers cannot produce exact results.
ce.precision = 'machine';
console.log(ce.parse('0.1 + 0.2').N().json);
// ➔ "0.30000000000000004"
While 0.1 and 0.2 look like "round numbers" in base-10, they can
only be represented by an approximation in base-2, which introduces cascading
errors when manipulating them.
Arbitrary Precision
If ce.precision is greater than 15, numbers are represented as bignum numbers,
a string of base-10 digits and an exponent.
Bignum numbers have a minimum value of \pm 10^{-9\,000\,000\,000\,000\,000} and a maximum value of \pm9.99999\ldots \times 10^{+9\,000\,000\,000\,000\,000}.
ce.precision = 21;
console.log(ce.parse('0.1 + 0.2').N().json);
// ➔ "0.3"
Trigonometric operations are accurate for precision up to 1,000.
Serialization and Precision
The precision property controls how computations are performed. It also
affects how results are displayed:
.latexand.toString()round numeric output toce.precisionsignificant digits. This hides noise digits that arise from internal rounding in division and transcendental functions..jsonandtoJSON()emit the full unrounded value for lossless data interchange. Useexpr.toMathJson({ fractionalDigits: 'auto' })to get precision-rounded MathJSON output.
To explicitly control digits in MathJSON output, use
expr.toMathJson() with the fractionalDigits option:
expr.toMathJson({ fractionalDigits: 'auto' }); // rounded to ce.precision
expr.toMathJson({ fractionalDigits: 'max' }); // all digits (default)
expr.toMathJson({ fractionalDigits: 5 }); // 5 fractional digits
When the precision is greater than 15, the return value of expr.N().json may
be a MathJSON number with a num string containing all available digits:
{
"num": "3.14159265358979323846264338327950288419716939937510"
}
The .json output may contain more digits than ce.precision because
some arithmetic operations (addition, subtraction, multiplication) are exact
and preserve all digits. Digits beyond the working precision are not
guaranteed to be accurate. For display purposes, use .latex or
.toString() which automatically round to the working precision.
Repeated Evaluation
To repeatedly evaluate an expression use ce.assign() to change the value
of variables. ce.assign() changes the value associated with one or more
variables in the current scope.
ce.assign() accepts booleans, numbers, bigints, expressions, or
functions. Use undefined to clear a value.
You can also use expr.subs(), but this will create a brand new expression on
each iteration, and will be much slower.
To reset a variable to be unbound to a value use ce.assign()
To change the value of a variable set its value property:
ce.symbol("x").value = 5;
ce.symbol("x").value = undefined;
Compiling
If performance is important, the expression can be compiled to a JavaScript function.
To get a compiled version of an expression use the compile() function:
import { compile } from '@cortex-js/compute-engine';
const result = compile("3x^2+4x+2");
for (const x = 0; x < 1; x += 0.01) console.log(result.run({ x }));
The syntax {x} is a shortcut for {"x": x}, in other words it defines an
argument named "x" (which is used in the definition of the expression expr)
with the value of the JavaScript variable x (which is used in the for loop).
This will usually result in a much faster evaluation than using expr.N() but
this approach has some limitations.
Simplifying Before Evaluating
When using expr.N(), no rewriting of the expression is done before it is
evaluated.
Because of the limitations of machine numbers, this may produce surprising results.
For example:
ce.precision = "machine";
const x = ce.parse("0.1 + 0.2").N();
console.log(ce.expr(["Subtract", x, x]).N());
// ➔ 2.7755575615628914e-17
However, the result of x - x from ce.simplify() is 0 since the
simplification is done symbolically, before any floating point calculations are
made.
const x = ce.parse('0.1 + 0.2').N();
console.log(ce.parse('x - x').simplify());
// ➔ 0
In some cases, it may be advantageous to invoke expr.simplify() before using
expr.N().
Tolerance
Two numbers that are sufficiently close to each other are considered equal.
To control how close two numbers have to be before they are considered
equal, set the tolerance property of a ComputeEngine instance.
By default, the tolerance is 10^{-10}.
The tolerance is accounted for by the Chop function to determine when to
replace a number of a small magnitude with the exact integer 0.
It is also used when doing some comparison to zero: a number whose absolute value is smaller than the tolerance will be considered equal to 0.
Numeric Functions
The topics below from the MathJSON Standard Library can provide numeric evaluations for their numeric functions:
| Topic | Symbols/Functions |
|---|---|
| Arithmetic | Add Multiply Power Exp Log ExponentialE ImaginaryUnit... |
| Calculus | Derivative Integrate... |
| Complex | Real Conjugate, ComplexRoots... |
| Special Functions | Gamma Factorial... |
| Statistics | StandardDeviation Mean Erf... |
| Trigonometry | Pi Cos Sin Tan... |