Differences with the original exp4j » History » Version 3
Federico Vera, 2018-07-12 06:00
| 1 | 3 | Federico Vera | {{>toc}} |
|---|---|---|---|
| 2 | 1 | Federico Vera | # Differences with the original exp4j |
| 3 | |||
| 4 | # Note |
||
| 5 | There are some key differences with original `exp4j`, some of which will cause compatibility issues for advanced `exp4j` users (API differences radicate in some corner cases). |
||
| 6 | |||
| 7 | # Core differences |
||
| 8 | This version of `exp4j` has several internal changes, which include but are not limited to: a naive simplifier, variable handling, extra functions, enums in code, constants as functions and token printing. |
||
| 9 | |||
| 10 | ## Naive Simplifier |
||
| 11 | The simplifier is a nice feature ([Original discussion](https://github.com/fasseg/exp4j/issues/26)) when you have operations that can be resolved the use of variables, for instance consider the expression `2^x + 4 / 2` could be turned into `2^x + 2`. Doesn't seem like much... does it? but when you use multiple formulas, lots of constants, multiple `x` values (i.e. plotting) this little difference comes in handy ([First performance test](https://github.com/fasseg/exp4j/issues/26#issuecomment-70547026)). |
||
| 12 | |||
| 13 | The other nice trick is when using expressions like `if(exp, v_true, v_false)`, the simplifier could remove the entire `if` block, for instance `if(1 > 0 & 3 < 4, a * pi(), e())` will be converted to `a * pi()` (actually to `if(1, a * pi(), e())`... _I'm still working on it..._ |
||
| 14 | |||
| 15 | ### Using the Simplifier |
||
| 16 | The simplifier is disabled by default, since it's really not needed when evaluating an expression only once (the simplifier needs to do one whole evaluation in order to work). |
||
| 17 | |||
| 18 | To activate it simply pass `true` to the builder: |
||
| 19 | |||
| 20 | ~~~java |
||
| 21 | // by default ExpressionBuilder#build() is #build(false) |
||
| 22 | Expression ex = new ExpressionBuilder("2^3 + 4 / 2").build(true); |
||
| 23 | double result = ex.evaluate(); |
||
| 24 | ~~~ |
||
| 25 | |||
| 26 | ### A little note |
||
| 27 | A simplifier _**should**_ only simplify deterministic functions, so there's now a `deterministic` flag in each function creation (`true` by default). So if you have [non-deterministic](https://en.wikipedia.org/wiki/Nondeterministic_algorithm) functions in your code, you'll need to change your function declaration from this: |
||
| 28 | |||
| 29 | ~~~java |
||
| 30 | Function rand_deterministic = new Function("randd", 0) { |
||
| 31 | @Override |
||
| 32 | public double apply(double... args) { |
||
| 33 | // This will be an epic simplification fail |
||
| 34 | return Math.random(); |
||
| 35 | } |
||
| 36 | }; |
||
| 37 | ~~~ |
||
| 38 | To this: |
||
| 39 | ~~~java |
||
| 40 | Function rand_NOT_deterministic = new Function("randnd", 0, false) { |
||
| 41 | // This flag ^^^^^ |
||
| 42 | @Override |
||
| 43 | public double apply(double... args) { |
||
| 44 | return Math.random(); |
||
| 45 | } |
||
| 46 | }; |
||
| 47 | ~~~ |
||
| 48 | |||
| 49 | This will be the most annoying thing for users with lot's of custom non-deterministic functions... although most users should not notice it (simplifier is disabled by default) |
||
| 50 | |||
| 51 | ## Internal variable handling |
||
| 52 | This isn't really an issue in itself, it makes `exp4j` gain some performance, avoid possible errors, and improve code readability. But doesn't honor the _inmutable token_ filosophy of both `exp4j` and stack based calculators, so if you want to start hacking in this fork you should take this into account. |
||
| 53 | |||
| 54 | ### So... what's the change? |
||
| 55 | 2 | Federico Vera | The real changes is commit:d2d96fce and in commit:7f280988 you can see an example of one the pitfalls. |
| 56 | 1 | Federico Vera | |
| 57 | The original `exp4j` uses one token per variable, that's to say one token each time a variable is present in an expression which creates every time a variable is set, a state where the same variable has a different values in an expression. That's really a no go for me. |
||
| 58 | |||
| 59 | This version of `exp4j` uses the same token for each and every time a variable is present in an expression, which means that the moment you set a variable it was changed in every occurrence. |
||
| 60 | |||
| 61 | ## Enums instead of final int variables |
||
| 62 | 2 | Federico Vera | This should not be a problem for anybody, but it's necessary to address the change `->` commit:39dff556. |
| 63 | 1 | Federico Vera | |
| 64 | ## Token printing |
||
| 65 | Some might call this a debugging tool, others the reason of a 50% increase in the final jar size, I simply call it token printing... it allowed me create a view of the internal expression. |
||
| 66 | ### Why should you care? |
||
| 67 | Well the thing is, you probably won't, but there are some cases when using this sort of tools for research you need a way to audit the internals of the expression, not to try and guarantee result reproducibility, but to build extra trust in the expression that's being evaluated (_also... it's an awesome debbuging tool!_). |
||
| 68 | ### How to print the tokens? |
||
| 69 | The two basic ways are: |
||
| 70 | ~~~java |
||
| 71 | Expression exp = new ExpressionBuilder("2x + 1").variable("x").build(); |
||
| 72 | String out1 = exp.toString(); |
||
| 73 | // out1 -> 2.0 x * 1.0 + |
||
| 74 | String out2 = exp.toTokenString(); |
||
| 75 | // out2 -> NUMBER[2.0] VARIABLE[x] OPERATOR[*] NUMBER[1.0] OPERATOR[+] |
||
| 76 | ~~~ |
||
| 77 | |||
| 78 | ## Constants as functions |
||
| 79 | We finally got to the change that will annoy most users and it's the change that will most probably _break_ things. In the original `exp4j` the constants where declared as simply constants, in this version constants are declared as functions so for instance `d * pi` is now `d * pi()`, this isn't an extreme change, but the reasoning is: some times your variables can have the name of constants... since users are not expected to know each and every constant implemented in `exp4j` this can cause trouble. |
||
| 80 | |||
| 81 | ## Extra functions |
||
| 82 | Checkout the wiki pages for: |
||
| 83 | * [[Built in Functions]] |
||
| 84 | * [[Built in Operators]] |
||
| 85 | * [[Extra Functions and Operators]] |