Differences with the original exp4j » Histórico » Versión 4
Federico Vera, 2018-07-12 06:01
1 | 1 | Federico Vera | |
---|---|---|---|
2 | 4 | Federico Vera | # Differences with the original exp4j |
3 | {{>toc}} |
||
4 | 1 | Federico Vera | # 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]] |