Typescript - evaluate arithmetic expressions Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!How to evaluate a math expression given in string form?What is TypeScript and why would I use it in place of JavaScript?Constructor overload in TypeScriptHow do you explicitly set a new property on `window` in TypeScript?Type definition in object literal in TypeScriptget and set in TypeScriptAre strongly-typed functions as parameters possible in TypeScript?TypeScript Converting a String to a numberTypescript: Interfaces vs TypesHow to implement class constants in typescript?Typescript, Express, Mocha & Chai Error while testing
When I export an AI 300x60 art board it saves with bigger dimensions
Show two Lagrangians are equivalent
Are there existing rules/lore for MTG planeswalkers?
All ASCII characters with a given bit count
Writing a T-SQL stored procedure to receive 4 numbers and insert them into a table
Translate text contents of an existing file from lower to upper case and copy to a new file
Protagonist's race is hidden - should I reveal it?
`FindRoot [ ]`::jsing: Encountered a singular Jacobian at a point...WHY
Co-worker works way more than he should
Can gravitational waves pass through a black hole?
Does using the Inspiration rules for character defects encourage My Guy Syndrome?
Is it OK if I do not take the receipt in Germany?
Simulate round-robin tournament draw
Why did Europeans not widely domesticate foxes?
Will I have to go through TSA security when I return to the US after preclearance?
SQL Server placement of master database files vs resource database files
Deciphering death certificate writing
Is there a way to fake a method response using Mock or Stubs?
Married in secret, can marital status in passport be changed at a later date?
Could typically electronic sounds be generated mechanically?
Cisco DHCP Router
Does a Draconic Bloodline sorcerer's doubled proficiency bonus for Charisma checks against dragons apply to all dragon types or only the chosen one?
Coin Game with infinite paradox
Why did Israel vote against lifting the American embargo on Cuba?
Typescript - evaluate arithmetic expressions
Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!How to evaluate a math expression given in string form?What is TypeScript and why would I use it in place of JavaScript?Constructor overload in TypeScriptHow do you explicitly set a new property on `window` in TypeScript?Type definition in object literal in TypeScriptget and set in TypeScriptAre strongly-typed functions as parameters possible in TypeScript?TypeScript Converting a String to a numberTypescript: Interfaces vs TypesHow to implement class constants in typescript?Typescript, Express, Mocha & Chai Error while testing
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
How can I evaluate arithmetic expressions in Typescript? An example is '(3+5*(-3+-1))'.
Eval(...) is forbidden.
A suggested solution is not accepted at runtime:
let input = '(3+5)';
let resultNumber = (new Function( 'return (' + input + ')'))();
The error is:
SyntaxError: Invalid or unexpected token
at new Function ()
Math.js with 136kb footprint (compressed) is too large in my for evaluating simple expressions. It could be customized by limiting the functionality.
So, do you have a small typescript file / service that can evaluate arithmetic expressions? Of course the unary minus/plus should work properly.
typescript
add a comment |
How can I evaluate arithmetic expressions in Typescript? An example is '(3+5*(-3+-1))'.
Eval(...) is forbidden.
A suggested solution is not accepted at runtime:
let input = '(3+5)';
let resultNumber = (new Function( 'return (' + input + ')'))();
The error is:
SyntaxError: Invalid or unexpected token
at new Function ()
Math.js with 136kb footprint (compressed) is too large in my for evaluating simple expressions. It could be customized by limiting the functionality.
So, do you have a small typescript file / service that can evaluate arithmetic expressions? Of course the unary minus/plus should work properly.
typescript
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
Make no mistake, if you thinkeval()is bad, thennew Function('');is just as bad for the exact same reasons.
– Evert
Mar 22 at 15:01
1
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
1
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44
add a comment |
How can I evaluate arithmetic expressions in Typescript? An example is '(3+5*(-3+-1))'.
Eval(...) is forbidden.
A suggested solution is not accepted at runtime:
let input = '(3+5)';
let resultNumber = (new Function( 'return (' + input + ')'))();
The error is:
SyntaxError: Invalid or unexpected token
at new Function ()
Math.js with 136kb footprint (compressed) is too large in my for evaluating simple expressions. It could be customized by limiting the functionality.
So, do you have a small typescript file / service that can evaluate arithmetic expressions? Of course the unary minus/plus should work properly.
typescript
How can I evaluate arithmetic expressions in Typescript? An example is '(3+5*(-3+-1))'.
Eval(...) is forbidden.
A suggested solution is not accepted at runtime:
let input = '(3+5)';
let resultNumber = (new Function( 'return (' + input + ')'))();
The error is:
SyntaxError: Invalid or unexpected token
at new Function ()
Math.js with 136kb footprint (compressed) is too large in my for evaluating simple expressions. It could be customized by limiting the functionality.
So, do you have a small typescript file / service that can evaluate arithmetic expressions? Of course the unary minus/plus should work properly.
typescript
typescript
edited Mar 23 at 11:30
halfer
14.8k759118
14.8k759118
asked Mar 22 at 14:51
tjm1706tjm1706
3,13932471
3,13932471
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
Make no mistake, if you thinkeval()is bad, thennew Function('');is just as bad for the exact same reasons.
– Evert
Mar 22 at 15:01
1
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
1
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44
add a comment |
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
Make no mistake, if you thinkeval()is bad, thennew Function('');is just as bad for the exact same reasons.
– Evert
Mar 22 at 15:01
1
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
1
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
Make no mistake, if you think
eval() is bad, then new Function(''); is just as bad for the exact same reasons.– Evert
Mar 22 at 15:01
Make no mistake, if you think
eval() is bad, then new Function(''); is just as bad for the exact same reasons.– Evert
Mar 22 at 15:01
1
1
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
1
1
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44
add a comment |
2 Answers
2
active
oldest
votes
Thanks to @Mathyn I found a piece of good Java code created by @Boann. I migrated it to Typescript, there you have it.
Below you also find the Karma test code, so you can see what is possible: +, -, (unary), *, ^, /, braces, (value), sin, cos, tan, sqrt, etc.
How to use it? In Angular, you can access it via dependency injection. Otherwise you can create an object. You can specify via a boolean (here 'true') to get the result as an integer.
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6') // shows 22.0
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6', true) // shows 22 (integer only)
The complete Typescript source code is:
export class ArithmeticExpressionEvaluator
static INVALID_NUMBER = -1234567.654;
str: string;
pos = -1;
ch: string;
evaluate(expression: string): number
return this.evaluateAll(expression, false);
evaluateAll(expression: string, resultIsInteger: boolean): number
this.str = expression;
pos = -1;
const outcome = this.parse();
if (resultIsInteger)
return Math.round(outcome);
return outcome;
nextChar()
this.ch = (++this.pos < this.str.length) ? this.str.charAt(this.pos) : null;
eat(charToEat: string): boolean
while (this.ch === ' ')
this.nextChar();
if (this.ch === charToEat)
this.nextChar();
return true;
return false;
parse(): number
this.nextChar();
const x = this.parseExpression();
if (this.pos < this.str.length)
return ArithmeticExpressionEvaluator.INVALID_NUMBER;
return x;
parseExpression(): number
let x = this.parseTerm();
for (; ; )
if (this.eat('+')) // addition
x += this.parseTerm();
else if (this.eat('-')) // subtraction
x -= this.parseTerm();
else
return x;
parseTerm(): number
let x = this.parseFactor();
for (; ;)
if (this.eat('*')) // multiplication
x *= this.parseFactor();
else if (this.eat('/')) // division
x /= this.parseFactor();
else
return x;
parseFactor(): number
degreesToRadians(degrees: number): number
const pi = Math.PI;
return degrees * (pi / 180);
The Karma test code is:
import ArithmeticExpressionEvaluator from './arithmetic-expression-evaluator.service';
describe('Arithmetic Expression Evaluation', () =>
let arithmeticExpressionEvaluator: ArithmeticExpressionEvaluator;
beforeEach(() =>
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator();
);
it('Arithmetic Expression Evaluation - double result', () =>
expect(arithmeticExpressionEvaluator.evaluate('10 + 2 * 6')).toBe(22.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + 12')).toBe(212.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * (2) + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('-100 * 2 + 12')).toBe(-188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 ^ 12')).toBe(409600.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('(100) * (( 2 ) + (12) )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 ) / 14')).toBe(100.0);
);
it('Arithmetic Expression Evaluation - integer result', () =>
expect(arithmeticExpressionEvaluator.evaluateAll('10 + 2 * 6', true)).toBe(22);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + 12' , true)).toBe(212);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * (2) + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('-100 * 2 + 12' , true)).toBe(-188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 ^ 12', true)).toBe(409600);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('(100) * (( 2 ) + (12) )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 ) / 14', true)).toBe(100);
);
);
add a comment |
If eval() is off the table, you need to write a custom DSL and write your own parser. To some extend you will build what eval() already does for you, but presumably a more restricted version without all the javascript features.
Alternatively find an existing NPM package.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55302276%2ftypescript-evaluate-arithmetic-expressions%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks to @Mathyn I found a piece of good Java code created by @Boann. I migrated it to Typescript, there you have it.
Below you also find the Karma test code, so you can see what is possible: +, -, (unary), *, ^, /, braces, (value), sin, cos, tan, sqrt, etc.
How to use it? In Angular, you can access it via dependency injection. Otherwise you can create an object. You can specify via a boolean (here 'true') to get the result as an integer.
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6') // shows 22.0
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6', true) // shows 22 (integer only)
The complete Typescript source code is:
export class ArithmeticExpressionEvaluator
static INVALID_NUMBER = -1234567.654;
str: string;
pos = -1;
ch: string;
evaluate(expression: string): number
return this.evaluateAll(expression, false);
evaluateAll(expression: string, resultIsInteger: boolean): number
this.str = expression;
pos = -1;
const outcome = this.parse();
if (resultIsInteger)
return Math.round(outcome);
return outcome;
nextChar()
this.ch = (++this.pos < this.str.length) ? this.str.charAt(this.pos) : null;
eat(charToEat: string): boolean
while (this.ch === ' ')
this.nextChar();
if (this.ch === charToEat)
this.nextChar();
return true;
return false;
parse(): number
this.nextChar();
const x = this.parseExpression();
if (this.pos < this.str.length)
return ArithmeticExpressionEvaluator.INVALID_NUMBER;
return x;
parseExpression(): number
let x = this.parseTerm();
for (; ; )
if (this.eat('+')) // addition
x += this.parseTerm();
else if (this.eat('-')) // subtraction
x -= this.parseTerm();
else
return x;
parseTerm(): number
let x = this.parseFactor();
for (; ;)
if (this.eat('*')) // multiplication
x *= this.parseFactor();
else if (this.eat('/')) // division
x /= this.parseFactor();
else
return x;
parseFactor(): number
degreesToRadians(degrees: number): number
const pi = Math.PI;
return degrees * (pi / 180);
The Karma test code is:
import ArithmeticExpressionEvaluator from './arithmetic-expression-evaluator.service';
describe('Arithmetic Expression Evaluation', () =>
let arithmeticExpressionEvaluator: ArithmeticExpressionEvaluator;
beforeEach(() =>
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator();
);
it('Arithmetic Expression Evaluation - double result', () =>
expect(arithmeticExpressionEvaluator.evaluate('10 + 2 * 6')).toBe(22.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + 12')).toBe(212.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * (2) + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('-100 * 2 + 12')).toBe(-188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 ^ 12')).toBe(409600.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('(100) * (( 2 ) + (12) )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 ) / 14')).toBe(100.0);
);
it('Arithmetic Expression Evaluation - integer result', () =>
expect(arithmeticExpressionEvaluator.evaluateAll('10 + 2 * 6', true)).toBe(22);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + 12' , true)).toBe(212);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * (2) + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('-100 * 2 + 12' , true)).toBe(-188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 ^ 12', true)).toBe(409600);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('(100) * (( 2 ) + (12) )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 ) / 14', true)).toBe(100);
);
);
add a comment |
Thanks to @Mathyn I found a piece of good Java code created by @Boann. I migrated it to Typescript, there you have it.
Below you also find the Karma test code, so you can see what is possible: +, -, (unary), *, ^, /, braces, (value), sin, cos, tan, sqrt, etc.
How to use it? In Angular, you can access it via dependency injection. Otherwise you can create an object. You can specify via a boolean (here 'true') to get the result as an integer.
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6') // shows 22.0
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6', true) // shows 22 (integer only)
The complete Typescript source code is:
export class ArithmeticExpressionEvaluator
static INVALID_NUMBER = -1234567.654;
str: string;
pos = -1;
ch: string;
evaluate(expression: string): number
return this.evaluateAll(expression, false);
evaluateAll(expression: string, resultIsInteger: boolean): number
this.str = expression;
pos = -1;
const outcome = this.parse();
if (resultIsInteger)
return Math.round(outcome);
return outcome;
nextChar()
this.ch = (++this.pos < this.str.length) ? this.str.charAt(this.pos) : null;
eat(charToEat: string): boolean
while (this.ch === ' ')
this.nextChar();
if (this.ch === charToEat)
this.nextChar();
return true;
return false;
parse(): number
this.nextChar();
const x = this.parseExpression();
if (this.pos < this.str.length)
return ArithmeticExpressionEvaluator.INVALID_NUMBER;
return x;
parseExpression(): number
let x = this.parseTerm();
for (; ; )
if (this.eat('+')) // addition
x += this.parseTerm();
else if (this.eat('-')) // subtraction
x -= this.parseTerm();
else
return x;
parseTerm(): number
let x = this.parseFactor();
for (; ;)
if (this.eat('*')) // multiplication
x *= this.parseFactor();
else if (this.eat('/')) // division
x /= this.parseFactor();
else
return x;
parseFactor(): number
degreesToRadians(degrees: number): number
const pi = Math.PI;
return degrees * (pi / 180);
The Karma test code is:
import ArithmeticExpressionEvaluator from './arithmetic-expression-evaluator.service';
describe('Arithmetic Expression Evaluation', () =>
let arithmeticExpressionEvaluator: ArithmeticExpressionEvaluator;
beforeEach(() =>
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator();
);
it('Arithmetic Expression Evaluation - double result', () =>
expect(arithmeticExpressionEvaluator.evaluate('10 + 2 * 6')).toBe(22.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + 12')).toBe(212.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * (2) + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('-100 * 2 + 12')).toBe(-188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 ^ 12')).toBe(409600.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('(100) * (( 2 ) + (12) )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 ) / 14')).toBe(100.0);
);
it('Arithmetic Expression Evaluation - integer result', () =>
expect(arithmeticExpressionEvaluator.evaluateAll('10 + 2 * 6', true)).toBe(22);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + 12' , true)).toBe(212);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * (2) + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('-100 * 2 + 12' , true)).toBe(-188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 ^ 12', true)).toBe(409600);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('(100) * (( 2 ) + (12) )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 ) / 14', true)).toBe(100);
);
);
add a comment |
Thanks to @Mathyn I found a piece of good Java code created by @Boann. I migrated it to Typescript, there you have it.
Below you also find the Karma test code, so you can see what is possible: +, -, (unary), *, ^, /, braces, (value), sin, cos, tan, sqrt, etc.
How to use it? In Angular, you can access it via dependency injection. Otherwise you can create an object. You can specify via a boolean (here 'true') to get the result as an integer.
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6') // shows 22.0
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6', true) // shows 22 (integer only)
The complete Typescript source code is:
export class ArithmeticExpressionEvaluator
static INVALID_NUMBER = -1234567.654;
str: string;
pos = -1;
ch: string;
evaluate(expression: string): number
return this.evaluateAll(expression, false);
evaluateAll(expression: string, resultIsInteger: boolean): number
this.str = expression;
pos = -1;
const outcome = this.parse();
if (resultIsInteger)
return Math.round(outcome);
return outcome;
nextChar()
this.ch = (++this.pos < this.str.length) ? this.str.charAt(this.pos) : null;
eat(charToEat: string): boolean
while (this.ch === ' ')
this.nextChar();
if (this.ch === charToEat)
this.nextChar();
return true;
return false;
parse(): number
this.nextChar();
const x = this.parseExpression();
if (this.pos < this.str.length)
return ArithmeticExpressionEvaluator.INVALID_NUMBER;
return x;
parseExpression(): number
let x = this.parseTerm();
for (; ; )
if (this.eat('+')) // addition
x += this.parseTerm();
else if (this.eat('-')) // subtraction
x -= this.parseTerm();
else
return x;
parseTerm(): number
let x = this.parseFactor();
for (; ;)
if (this.eat('*')) // multiplication
x *= this.parseFactor();
else if (this.eat('/')) // division
x /= this.parseFactor();
else
return x;
parseFactor(): number
degreesToRadians(degrees: number): number
const pi = Math.PI;
return degrees * (pi / 180);
The Karma test code is:
import ArithmeticExpressionEvaluator from './arithmetic-expression-evaluator.service';
describe('Arithmetic Expression Evaluation', () =>
let arithmeticExpressionEvaluator: ArithmeticExpressionEvaluator;
beforeEach(() =>
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator();
);
it('Arithmetic Expression Evaluation - double result', () =>
expect(arithmeticExpressionEvaluator.evaluate('10 + 2 * 6')).toBe(22.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + 12')).toBe(212.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * (2) + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('-100 * 2 + 12')).toBe(-188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 ^ 12')).toBe(409600.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('(100) * (( 2 ) + (12) )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 ) / 14')).toBe(100.0);
);
it('Arithmetic Expression Evaluation - integer result', () =>
expect(arithmeticExpressionEvaluator.evaluateAll('10 + 2 * 6', true)).toBe(22);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + 12' , true)).toBe(212);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * (2) + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('-100 * 2 + 12' , true)).toBe(-188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 ^ 12', true)).toBe(409600);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('(100) * (( 2 ) + (12) )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 ) / 14', true)).toBe(100);
);
);
Thanks to @Mathyn I found a piece of good Java code created by @Boann. I migrated it to Typescript, there you have it.
Below you also find the Karma test code, so you can see what is possible: +, -, (unary), *, ^, /, braces, (value), sin, cos, tan, sqrt, etc.
How to use it? In Angular, you can access it via dependency injection. Otherwise you can create an object. You can specify via a boolean (here 'true') to get the result as an integer.
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6') // shows 22.0
arithmeticExpressionEvaluator.evaluate('10 + 2 * 6', true) // shows 22 (integer only)
The complete Typescript source code is:
export class ArithmeticExpressionEvaluator
static INVALID_NUMBER = -1234567.654;
str: string;
pos = -1;
ch: string;
evaluate(expression: string): number
return this.evaluateAll(expression, false);
evaluateAll(expression: string, resultIsInteger: boolean): number
this.str = expression;
pos = -1;
const outcome = this.parse();
if (resultIsInteger)
return Math.round(outcome);
return outcome;
nextChar()
this.ch = (++this.pos < this.str.length) ? this.str.charAt(this.pos) : null;
eat(charToEat: string): boolean
while (this.ch === ' ')
this.nextChar();
if (this.ch === charToEat)
this.nextChar();
return true;
return false;
parse(): number
this.nextChar();
const x = this.parseExpression();
if (this.pos < this.str.length)
return ArithmeticExpressionEvaluator.INVALID_NUMBER;
return x;
parseExpression(): number
let x = this.parseTerm();
for (; ; )
if (this.eat('+')) // addition
x += this.parseTerm();
else if (this.eat('-')) // subtraction
x -= this.parseTerm();
else
return x;
parseTerm(): number
let x = this.parseFactor();
for (; ;)
if (this.eat('*')) // multiplication
x *= this.parseFactor();
else if (this.eat('/')) // division
x /= this.parseFactor();
else
return x;
parseFactor(): number
degreesToRadians(degrees: number): number
const pi = Math.PI;
return degrees * (pi / 180);
The Karma test code is:
import ArithmeticExpressionEvaluator from './arithmetic-expression-evaluator.service';
describe('Arithmetic Expression Evaluation', () =>
let arithmeticExpressionEvaluator: ArithmeticExpressionEvaluator;
beforeEach(() =>
arithmeticExpressionEvaluator = new ArithmeticExpressionEvaluator();
);
it('Arithmetic Expression Evaluation - double result', () =>
expect(arithmeticExpressionEvaluator.evaluate('10 + 2 * 6')).toBe(22.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + 12')).toBe(212.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * (2) + -12')).toBe(188.0);
expect(arithmeticExpressionEvaluator.evaluate('-100 * 2 + 12')).toBe(-188.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * 2 ^ 12')).toBe(409600.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('(100) * (( 2 ) + (12) )')).toBe(1400.0);
expect(arithmeticExpressionEvaluator.evaluate('100 * ( 2 + 12 ) / 14')).toBe(100.0);
);
it('Arithmetic Expression Evaluation - integer result', () =>
expect(arithmeticExpressionEvaluator.evaluateAll('10 + 2 * 6', true)).toBe(22);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + 12' , true)).toBe(212);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * (2) + -12', true)).toBe(188);
expect(arithmeticExpressionEvaluator.evaluateAll('-100 * 2 + 12' , true)).toBe(-188);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * 2 ^ 12', true)).toBe(409600);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('(100) * (( 2 ) + (12) )', true)).toBe(1400);
expect(arithmeticExpressionEvaluator.evaluateAll('100 * ( 2 + 12 ) / 14', true)).toBe(100);
);
);
edited Mar 23 at 21:15
answered Mar 22 at 18:27
tjm1706tjm1706
3,13932471
3,13932471
add a comment |
add a comment |
If eval() is off the table, you need to write a custom DSL and write your own parser. To some extend you will build what eval() already does for you, but presumably a more restricted version without all the javascript features.
Alternatively find an existing NPM package.
add a comment |
If eval() is off the table, you need to write a custom DSL and write your own parser. To some extend you will build what eval() already does for you, but presumably a more restricted version without all the javascript features.
Alternatively find an existing NPM package.
add a comment |
If eval() is off the table, you need to write a custom DSL and write your own parser. To some extend you will build what eval() already does for you, but presumably a more restricted version without all the javascript features.
Alternatively find an existing NPM package.
If eval() is off the table, you need to write a custom DSL and write your own parser. To some extend you will build what eval() already does for you, but presumably a more restricted version without all the javascript features.
Alternatively find an existing NPM package.
answered Mar 22 at 14:57
EvertEvert
42.7k1572127
42.7k1572127
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55302276%2ftypescript-evaluate-arithmetic-expressions%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This post while asked for Java might contain some info which can help you out. Maybe you can rewrite some of the code to Javascript/Typescript?
– Mathyn
Mar 22 at 14:55
Make no mistake, if you think
eval()is bad, thennew Function('');is just as bad for the exact same reasons.– Evert
Mar 22 at 15:01
1
@Mathyn - GREAT - via your post I found a very compact evaluation of arithmetic expressions. Can you add this link to an Answer, and I will +1 it! stackoverflow.com/a/26227947/3143823
– tjm1706
Mar 22 at 15:22
1
@tjm1706 I'd love to but I'd have to rewrite the Java code to Typescript myself for it to be a proper answer.
– Mathyn
Mar 22 at 15:31
I am already rewriting the code. You pointed me the way for a solution. So you can post that answer.
– tjm1706
Mar 22 at 15:44