Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ParserNG should use BigDecimal instead of double #30

Open
JellyBrick opened this issue Feb 6, 2023 · 16 comments
Open

ParserNG should use BigDecimal instead of double #30

JellyBrick opened this issue Feb 6, 2023 · 16 comments

Comments

@JellyBrick
Copy link

JellyBrick commented Feb 6, 2023

Test code

class MathTest {
    @Test
    fun testMathExpression() {
        println(MathExpression("239081204214*1247981247912749").solve())
    }
}

Expect

298368859587470504923124286

Result

298368859587470500000000000

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

The parserng works by default in doubles. What you see is max precision double can get:

jshell> double a = 239081204214d
a ==> 2.39081204214E11
jshell> double b=1247981247912749d
b ==> 1.247981247912749E15
jshell> a*b
$3 ==> 2.983688595874705E26

What you see would be achieved moving whole parserng to bigdecimal:

jshell> BigInteger ba = new BigInteger("239081204214");
ba ==> 239081204214
jshell> BigInteger bb = new BigInteger("1247981247912749");
bb ==> 1247981247912749
jshell> BigInteger bc =ba.multiply(bb)
bc ==> 298368859587470504923124286

and big decimal

jshell> BigDecimal ba = new BigDecimal("239081204214");
ba ==> 239081204214
jshell> BigDecimal bb = new BigDecimal("1247981247912749");
bb ==> 1247981247912749
jshell> ba.multiply(bb)
$3 ==> 298368859587470504923124286

Where the cost performance will be notable, I would vote for moveing parserng from double to BigInteger. Still it is very huge step.

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

I would probably recommend to change subject of this issue: "parserng shoud use bigdecimal instead of doubles" , but still, I think its not going to be solved anytime soon.

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

btw, future 0.1.9 (pom is not yet bumped) have sum and gsum rewritten to biginteger:

java -jar target/parser-ng-0.1.8.jar  "gsum(239081204214,1247981247912749)"
298368859587470504923124286

(prod is still in double):

java -jar target/parser-ng-0.1.8.jar  "prod(239081204214,1247981247912749)"
2.983688595874705E26

So gsum/summ can help you to workaroudn this problem.. somehow...

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

I hope to draft readme.md changes for 0.1.9 during this week, so @gbenroscience could release.

@JellyBrick JellyBrick changed the title The result is not as expected (can't adjustable precision) ParserNG should use BigDecimal instead of double Feb 6, 2023
@JellyBrick
Copy link
Author

JellyBrick commented Feb 6, 2023

The parserng works by default in doubles. What you see is max precission double can get:

jshell> double a = 239081204214d
a ==> 2.39081204214E11
jshell> double b=1247981247912749d
b ==> 1.247981247912749E15
jshell> a*b
$3 ==> 2.983688595874705E26

What you see would be achieved moving whole parserng to bigdecimal:

jshell> BigInteger ba = new BigInteger("239081204214");
ba ==> 239081204214
jshell> BigInteger bb = new BigInteger("1247981247912749");
bb ==> 1247981247912749
jshell> BigInteger bc =ba.multiply(bb)
bc ==> 298368859587470504923124286

Where the cost performance will be notable, I would vote for moveing parserng from double to BigInteger. Still it is very huge step.

https://github.com/ezylang/EvalEx-big-math

How about delegating BigDecimal operations to other extension libraries? (e.g. EvalEx <-> EvalEx-big-math)

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

https://github.com/ezylang/EvalEx-big-math

How about delegating BigDecimal operations to other extension libraries? (e.g. EvalEx <-> EvalEx-big-math)

Well there is plenty of math libraries, each with its pros and cons. Some ar fast, some ar not, some have some functins, some dont, some are double, some are bigdecimal.... I like pareserng for its strightforward approach and easy extendability. To have math library(parserng) calling another math library (evalex-bigmath) would be very weird step.

@judovana
Copy link
Contributor

judovana commented Feb 6, 2023

Thanx for fixing me to BigDecimal. My typo. Had BigDecimal in mind.

@JellyBrick
Copy link
Author

ezylang/EvalEx-big-math
How about delegating BigDecimal operations to other extension libraries? (e.g. EvalEx <-> EvalEx-big-math)

Well there is plenty of math libraries, each with its pros and cons. Some ar fast, some ar not, some have some functins, some dont, some are double, some are bigdecimal.... I like pareserng for its strightforward approach and easy extendability. To have math library(parserng) calling another math library (evalex-bigmath) would be very weird step.

What I'm saying is that there are cases like EvalEx-big-math. I'm not saying that ParserNG should include EvalEx-big-math.

@gbenroscience
Copy link
Owner

gbenroscience commented Feb 7, 2023

Hello @JellyBrick , thanks for using ParserNG!
Thanks @judovana for responding.

@JellyBrick , BigDecimal computations would definitely slow down the parser and this is why we use double precision instead!

However, we can define a limited BigMathExpression class that handles no functions, just algebraic expressions.
This would bring limited support of your functionality to ParserNG.

Many important classes are based on MathExpression and we don't want something like this to break something higher up in the chain.

With time, then we can contribute functions that efficiently and accurately compute the trig functions, the log functions etc in BigDecimal format.

Once this is achieved, we can then allow BigMathExpression support functions also.

What do you think, @judovana and @JellyBrick ?

@gbenroscience
Copy link
Owner

gbenroscience commented Feb 7, 2023

Actually, there is a class PolynomialExpression that does this already, buried somewhere in the heart of ParserNG. It is used mainly by numerical methods for integral calculus and some other functionality, I think, in the parser.
If you are cool with it, we can base this functionality on it and move ahead.

@judovana
Copy link
Contributor

judovana commented Feb 7, 2023

Can you provide examples of PolynomialExpression please?

The BigMathExpression is interesting idea. Maybe MathExpression can have as parameter factory method, which will be responsible for sting->number convertions? like T toNumber(String) which in MathExpression will return Double, and otherwise BigDecimal. The mian issue here is the Double x double. In all cases this will get rid of primitives, whcih you do not want I guess. Still having BigDecimal at elast semi optional, sounds exceptionally god.

Before actuallys tarting anything, would be nice to have performance comparsion double x Double x BigDecimal. Maybe the difference will bs super trivial.

@gbenroscience
Copy link
Owner

gbenroscience commented Feb 7, 2023

PolynomialExpression

So sorry. I took a look at PolynomialExpression and its not what I had in mind that it does. Its quite old code but it contains a lot of things that can be reused in an hypothetical BigMathExpression class.

Before actually starting anything, would be nice to have performance comparison double x Double x BigDecimal. Maybe the difference will be super trivial.

Did some research online though, it seems the general consensus is that BigDecimal would be much slower versus primitives. One such article is this

@judovana
Copy link
Contributor

judovana commented Feb 7, 2023

I have bigger concerns about double x Double. Which is killing the idea of generic MathExpression. Still worthy to investigate in future. I personally would like to see whole ParserNG on BigDecimal. But that would be tremendous work with sporadic result. generic MathExpression would be incredible solution. It would allow also predictable default length of fractional part of number.

@gbenroscience
Copy link
Owner

gbenroscience commented Feb 7, 2023

Considering the fact that I pray God that a time would come when I would have enough time on my hands to do a speed optimized refactor of ParserNG, moving all of ParserNG to BigDecimal is definitely not attractive to me.
But I do not mind having robust BigDecimal support via inheritance(extension...e.g BigMathExpression, preferable) or via setting modes(e.g. DOUBLE or BIGDECIMAL) on the MathExpression class(not so attractive).

I have bigger concerns about double x Double.

Double would benchmark slower than double also; that is the popular opinion since Double is an object. But you could run some tests to convince us of this.

@judovana
Copy link
Contributor

judovana commented Feb 7, 2023

Yup. Sure. Crossing fingers for you, and agreeing on double x Double.

@gbenroscience
Copy link
Owner

Hi @judovana and @JellyBrick, here is PR #32

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants