diff --git a/src/lexer.ts b/src/lexer.ts index e998ff4..59d86da 100644 --- a/src/lexer.ts +++ b/src/lexer.ts @@ -59,6 +59,7 @@ var type3Asterick: Allowed = { }; // type_5:true,type_7:true,type_23 var type6: Allowed = { 1: true, + 3: true, }; var newAr = [ [], @@ -83,6 +84,7 @@ var newAr = [ "P", "C", "e", + "E", "0", ".", ",", @@ -279,6 +281,33 @@ export const lex = function (this: Mexp, inp: string, tokens?: Token[]) { if (allowed[cType] !== true) { throw new Error(cToken + " is not allowed after " + prevKey); } + if ( + (cToken === "e" || cToken === "E") && + pre.type === tokenTypes.NUMBER && + i < nodes.length - 1 + ) { + var next = nodes[i + 1]; + var isScientific = false; + if (next.type === tokenTypes.NUMBER) { + isScientific = true; + } else if ( + (next.token === "+" || next.token === "-") && + i < nodes.length - 2 && + nodes[i + 2].type === tokenTypes.NUMBER + ) { + isScientific = true; + } + if (isScientific) { + pre.value += "e"; + if (next.type !== tokenTypes.NUMBER) { + pre.value += next.token; + i++; + } + allowed = type6; + asterick = empty; + continue; + } + } if (asterick[cType] === true) { cType = tokenTypes.BINARY_OPERATOR_HIGH_PRECENDENCE; cEv = this.math.mul; diff --git a/src/token.ts b/src/token.ts index b980d8f..bcc71ad 100644 --- a/src/token.ts +++ b/src/token.ts @@ -67,6 +67,7 @@ export const createTokens = (mexp: Mexp) => { { token: 'sinh', show: 'sinh', type: 0, value: mexp.math.sinh }, { token: 'asinh', show: 'asinh', type: 0, value: mexp.math.asinh }, { token: 'e', show: 'e', type: 3, value: 'E' }, + { token: 'E', show: 'E', type: 3, value: 'E' }, { token: 'log', show: ' log', type: 0, value: mexp.math.log }, { token: '0', show: '0', type: 1, value: '0' }, { token: '.', show: '.', type: 6, value: '.' }, diff --git a/test/scientific-notation.js b/test/scientific-notation.js new file mode 100644 index 0000000..6475138 --- /dev/null +++ b/test/scientific-notation.js @@ -0,0 +1,39 @@ +var assert = require('assert') +var Mexp = require('../dist/es/index.js') +var mexp = new Mexp() + +describe('Scientific notation', function () { + it('should parse 1e-7 correctly', function () { + assert.equal(mexp.eval('1e-7'), 0.0000001) + }) + it('should parse 1e+7 correctly', function () { + assert.equal(mexp.eval('1e+7'), 10000000) + }) + it('should parse 1e7 correctly', function () { + assert.equal(mexp.eval('1e7'), 10000000) + }) + it('should parse 1.5e-2 correctly', function () { + assert.equal(mexp.eval('1.5e-2'), 0.015) + }) + it('should parse capital E correctly', function () { + assert.equal(mexp.eval('1E-7'), 0.0000001) + }) + it('should parse complex expressions with scientific notation', function () { + assert.equal(mexp.eval('1e-7*10'), 0.000001) + }) + it('should parse scientific notation with addition', function () { + assert.equal(mexp.eval('1e3+500'), 1500) + }) + it('should parse scientific notation in functions', function () { + assert.equal(mexp.eval('log(1e2)'), 2) + }) + it('should handle zero exponent correctly', function () { + assert.equal(mexp.eval('5e0'), 5) + }) + it('should still support Euler constant e', function () { + assert.equal(mexp.eval('e'), Math.E) + }) + it('should distinguish between Euler constant e and scientific notation', function () { + assert.equal(mexp.eval('e-1e-1+e'), Math.E - 0.1 + Math.E) + }) +})