Differences with the original exp4j » Histórico » Versión 1
Federico Vera, 2018-06-09 23:51
1 | 1 | Federico Vera | # Differences with the original exp4j |
---|---|---|---|
2 | |||
3 | # Note |
||
4 | 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). |
||
5 | |||
6 | # Core differences |
||
7 | 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. |
||
8 | |||
9 | ## Naive Simplifier |
||
10 | 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)). |
||
11 | |||
12 | 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..._ |
||
13 | |||
14 | ### Using the Simplifier |
||
15 | 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). |
||
16 | |||
17 | To activate it simply pass `true` to the builder: |
||
18 | |||
19 | ~~~java |
||
20 | // by default ExpressionBuilder#build() is #build(false) |
||
21 | Expression ex = new ExpressionBuilder("2^3 + 4 / 2").build(true); |
||
22 | double result = ex.evaluate(); |
||
23 | ~~~ |
||
24 | |||
25 | ### A little note |
||
26 | 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: |
||
27 | |||
28 | ~~~java |
||
29 | Function rand_deterministic = new Function("randd", 0) { |
||
30 | @Override |
||
31 | public double apply(double... args) { |
||
32 | // This will be an epic simplification fail |
||
33 | return Math.random(); |
||
34 | } |
||
35 | }; |
||
36 | ~~~ |
||
37 | To this: |
||
38 | ~~~java |
||
39 | Function rand_NOT_deterministic = new Function("randnd", 0, false) { |
||
40 | // This flag ^^^^^ |
||
41 | @Override |
||
42 | public double apply(double... args) { |
||
43 | return Math.random(); |
||
44 | } |
||
45 | }; |
||
46 | ~~~ |
||
47 | |||
48 | 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) |
||
49 | |||
50 | ## Internal variable handling |
||
51 | 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. |
||
52 | |||
53 | ### So... what's the change? |
||
54 | The real change is [this](https://github.com/dktcoding/exp4j/commit/d2d96fce7e510a15ae53d406d238417c03c51ea6) and [here](https://github.com/dktcoding/exp4j/pull/3) you can see an example of one the pitfalls. |
||
55 | |||
56 | 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. |
||
57 | |||
58 | 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. |
||
59 | |||
60 | ## Enums instead of final int variables |
||
61 | This should not be a problem for anybody, but it's necessary to address the [change](https://github.com/dktcoding/exp4j/commit/39dff556cd94fb671baeefc7aaee981f7e4be367). |
||
62 | |||
63 | ## Token printing |
||
64 | 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. |
||
65 | ### Why should you care? |
||
66 | 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!_). |
||
67 | ### How to print the tokens? |
||
68 | The two basic ways are: |
||
69 | ~~~java |
||
70 | Expression exp = new ExpressionBuilder("2x + 1").variable("x").build(); |
||
71 | String out1 = exp.toString(); |
||
72 | // out1 -> 2.0 x * 1.0 + |
||
73 | String out2 = exp.toTokenString(); |
||
74 | // out2 -> NUMBER[2.0] VARIABLE[x] OPERATOR[*] NUMBER[1.0] OPERATOR[+] |
||
75 | ~~~ |
||
76 | |||
77 | ## Constants as functions |
||
78 | 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. |
||
79 | |||
80 | ## Extra functions |
||
81 | Checkout the wiki pages for: |
||
82 | * [[Built in Functions]] |
||
83 | * [[Built in Operators]] |
||
84 | * [[Extra Functions and Operators]] |