Better handling of constants in simplified expressions.

This commit is contained in:
Ad5001 2023-10-09 18:37:28 +02:00
parent bc35b18da0
commit cf754a7a34
Signed by: Ad5001
GPG key ID: EF45F9C6AFE20160
5 changed files with 37 additions and 15 deletions

View file

@ -521,7 +521,7 @@ Expression.prototype.substitute = function (variable, expr) {
};
Expression.prototype.evaluate = function (values) {
values = values || {};
values = Object.assign({}, values, this.parser.consts)
return evaluate(this.tokens, this, values);
};
@ -541,8 +541,9 @@ Expression.prototype.variables = function (options) {
var vars = [];
getSymbols(this.tokens, vars, options);
var functions = this.functions;
var consts = this.parser.consts
return vars.filter(function (name) {
return !(name in functions);
return !(name in functions) && !(name in consts);
});
};
@ -580,7 +581,7 @@ function TokenStream(parser, expression) {
this.unaryOps = parser.unaryOps;
this.binaryOps = parser.binaryOps;
this.ternaryOps = parser.ternaryOps;
this.consts = parser.consts;
this.builtinConsts = parser.builtinConsts;
this.expression = expression;
this.savedPosition = 0;
this.savedCurrent = null;
@ -700,8 +701,8 @@ TokenStream.prototype.isConst = function () {
}
if (i > startPos) {
var str = this.expression.substring(startPos, i);
if (str in this.consts) {
this.current = this.newToken(TNUMBER, this.consts[str]);
if (str in this.builtinConsts) {
this.current = this.newToken(TNUMBER, this.builtinConsts[str]);
this.pos += str.length;
return true;
}
@ -1792,12 +1793,12 @@ class Parser {
join: arrayJoin
};
this.consts = {
E: Math.E,
PI: Math.PI,
'true': true,
'false': false
};
// These constants will automatically be replaced the MOMENT they are parsed.
// (Original consts from the parser)
this.builtinConsts = {};
// These consts will only be replaced when the expression is evaluated.
this.consts = {}
}
parse(expr) {

View file

@ -26,13 +26,17 @@ const DERIVATION_PRECISION = 0.1
var evalVariables = { // Variables not provided by expr-eval.js, needs to be provided manually
"pi": Math.PI,
"PI": Math.PI,
"π": Math.PI,
"inf": Infinity,
"infinity": Infinity,
"Infinity": Infinity,
"∞": Infinity,
"e": Math.E,
"E": Math.E
"E": Math.E,
"true": true,
"false": false
}
var currentVars = {}
@ -54,3 +58,4 @@ parser.functions.derivative = function(f, variable, x) {
f = parser.parse(f).toJSFunction(variable, currentVars)
return (f(x+DERIVATION_PRECISION/2)-f(x-DERIVATION_PRECISION/2))/DERIVATION_PRECISION
}

View file

@ -27,8 +27,8 @@
*/
class Expression {
constructor(expr) {
this.expr = expr
this.calc = C.parser.parse(expr).simplify()
this.expr = Utils.exponentsToExpression(expr)
this.calc = C.parser.parse(this.expr).simplify()
this.cached = this.isConstant()
this.cachedValue = this.cached && this.allRequirementsFullfilled() ? this.calc.evaluate(C.currentObjectsByName) : null
this.latexMarkup = Latex.expression(this.calc.tokens)

View file

@ -62,6 +62,11 @@ var powerpos = {
"z": "ᶻ"
}
var exponents = [
"⁰","¹","²","³","⁴","⁵","⁶","⁷","⁸","⁹"
]
var exponentReg = new RegExp('(['+exponents.join('')+']+)', 'g')
var indicepos = {
"-": "₋",
"+": "₊",
@ -351,3 +356,14 @@ function getRandomColor() {
function escapeHTML(str) {
return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
}
/**
* Parses exponents and replaces them with expression values
* @param {string} expression - The expression to replace in.
* @return {string} The parsed expression
*/
function exponentsToExpression(expression) {
return expression.replace(exponentReg, (m, exp) => '^' + exp.split('').map((x) => exponents.indexOf(x)).join(''))
}

View file

@ -79,4 +79,4 @@ Language files translations located at LogarithmPlotter/i18n are licensed under
LogarithmPlotter includes [expr-eval](https://github.com/silentmatt/expr-eval) a port of [ndef.parser](https://web.archive.org/web/20111023001618/http://www.undefined.ch/mparser/index.html) by Raphael Graf &lt;r@undefined.ch&gt;, ported to javascript by Matthew Crumley &lt;email@matthewcrumley.com&gt; (http://silentmatt.com/), and then to QMLJS by Ad5001.
The code is licensed under the [MIT License](https://raw.githubusercontent.com/silentmatt/expr-eval/master/LICENSE.txt).
The specific file (LogarithmPlotter/qml/eu/ad5001/LogarithmPlotter/js/expr-eval.js) is licensed under the [MIT License](https://raw.githubusercontent.com/silentmatt/expr-eval/master/LICENSE.txt).