nicklockwood / Expression

A cross-platform Swift library for evaluating mathematical expressions at runtime
MIT License
829 stars 51 forks source link

Unexpected result related to whitespace and operators #19

Closed zcohan closed 5 years ago

zcohan commented 5 years ago

I'm running into an issue where the absence of a whitespace character before a '+' operator in some cases has an affect on the result. For instance:

Expression("3 * 4 +5").evaluate() // 27.0
Expression("3 * 4 + 5").evaluate() // 17.0
Expression("3*4+5").evaluate() // 17.0

I believe this to be a bug.

nicklockwood commented 5 years ago

@zcohan you're right, this isn't expected behavior. I'll take a look, thanks.

zcohan commented 5 years ago

Thanks. I was also surprised by some results related to spaces and subtracting negative numbers.

Many expression based calculators accept all the following syntaxes:

Expression("20 - -20").evaluate() //40.0
Expression("20--20").evaluate() //error 
Expression("20 -- 20").evaluate() //error
Expression("20 - - 20).evaluate() //error
nicklockwood commented 5 years ago

@zcohan those latter examples are expected. Expression allows the caller to define custom operators, which means it can't distinguish between an infix -- operator vs an infix - operator followed by a prefix - operator unless the whitespace makes it unambiguous.

zcohan commented 5 years ago

Fair enough. To minimise surprise, perhaps it would make sense to set some "sensible defaults" if there are no custom operators defined (given those expressions are mathematically equivalent).

nicklockwood commented 5 years ago

I'm running into an issue where the absence of a whitespace character before a '+' operator in some cases has an affect on the result. For instance:

@zcohan this is now fixed in 0.12.12.

To minimise surprise, perhaps it would make sense to set some "sensible defaults" if there are no custom operators defined.

I did experiment with this, but is was a big unsatisfactory for various reasons. E.g. if you overrode the "+" operator with a custom method, and then someone wrote "a+-b" it would call the internal "+-" operator instead of your overridden "+".

It's probably not insurmountable, but if you want this behavior you can already implement "+-", "--", etc yourself as custom operators.