eobermuhlner / big-math Goto Github PK
View Code? Open in Web Editor NEWAdvanced Java BigDecimal math functions (pow, sqrt, log, sin, ...) using arbitrary precision.
License: MIT License
Advanced Java BigDecimal math functions (pow, sqrt, log, sin, ...) using arbitrary precision.
License: MIT License
Consider the following example which shows why the method fails and an alternative (Float.valueOf(x.toBigDecimal().toString())) that works more how I expected, but would fail if x could not be represented as a BigDecimal.
BigRational x = BigRational.valueOf("8.804462619980757911125181749462772084351754080848495898653087767533866267556634");
System.out.println(x.toRationalString());
System.out.println(x.toFloat());
System.out.println(Float.valueOf(x.toBigDecimal().toString()));
System.out.println(new BigDecimal("1000000000000000000000000000000000000000000000000000000000000000000000000000000").floatValue());
Another missing convenience method of BigDecimal.
The next code throws Overflow error
BigDecimalMath.pow(new BigDecimal("85"), new BigDecimal("483379540.5878915618046344614959831"), MathContext.DECIMAL128)
expected result
new BigDecimal("8.191399333915731143433650968385840E+932641633")
In attachment you can find the fix (Intellij IDEA patch file)
bugfix_pow_special_case_overflow.patch
Negative rational numbers smaller than 1 are printed without -
sign.
For example:
BigRational v = valueOf(-1, 2);
System.out.println("small negative rational toString(): " + v);
System.out.println("small negative rational toIntegerRationalString(): " + v);
prints:
small negative rational toString(): -0.5
small negative rational toIntegerRationalString(): 1/2
build.gradle
uploadArtifacts
in build.gradle
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
Release
own Repositorydocs/javadoc
docs/index.md
The implementation of the factorial method provides only an integer argument, which does not match the definition found in the README documentation.
The method should use factorial(int, MathContext)
rather than factorial(int)
, according to the documentation.
Additionally, for the sake of consistency, I think the factorial method should take a BigDecimal rather than an integer. Inputting a fractional factorial should simply use the gamma function.
The BigDecimalMath.root(BigDecimal, BigDecimal, MathContext)
function converges very slowly for larger values of n
.
This is due to a bad initial value for the Newton-Raphson approximation.
Use double
calculations for the initial value with a fallback to pow(x, 1/n).
Hello
I think there may be a little typo in atan2() . On line 1033 of BigDecimalMath there is
return atan(y.divide(x, 3), mathContext);
which I think should be
return atan(y.divide(x, mc), mathContext);
See:
https://en.wikipedia.org/wiki/Atan2
Measure performance of different implementations over the full range of values.
Add a class BigComplex (or similar name, maybe BigDecimalComplex) with basic arithmetic support - similar design to BigDecimal.
Add a class BigComplexMath with static math functions in the complex domain.
template_release_note.md
build.gradle
./gradlew clean
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
until Release
becomes enabledRelease
own Repositorydocs/javadoc
docs/index.md
build.gradle
to use new release librarysettings.gradle
to add new regression project./gradlew :regression.v2_2_1:run
(verify version number) with standard machineanalysis/*.csv
files to add new release numberscsv2chart --property chart=line *.csv
in directory regression/analysis
Maybe these are helpful: https://mathworld.wolfram.com/SquareRoot.html and org.apache.commons.numbers.complex.Complex#sqrt() from org.apache.commons:commons-numbers-complex.
I know that this is not related to the code on this repo, but I just wanted to ask if there is a way to implement a function that returns the double value approximation of a bigdecimal. The original implementation (at least for java 8 uses string operations in order to construct that representation which makes it incredibly slow).
If nothing can be done, then please go ahead and close this ticket.
Thank you very much
When BigComplexMath.sqrt
is invoked with an argument that has a negative or zero real part and a zero imaginary part, it throws an ArithmeticException
:
BigComplexMath.sqrt(BigComplex.ONE.negate(), MathContext.DECIMAL64)
Exception in thread "main" java.lang.ArithmeticException: Division undefined
at java.base/java.math.BigDecimal.divide(BigDecimal.java:1831)
at ch.obermuhlner.math.big.BigComplex.divide(BigComplex.java:287)
at ch.obermuhlner.math.big.BigComplexMath.sqrt(BigComplexMath.java:289)
BigComplexMath.sqrt
should not throw an ArithmeticException
but compute the result (in the above case 0 + 1i
) instead.
BigDecimalMath.sqrt
rounding isn't always correct. Three examples:
// OpenJDK 15
BigDecimal x;
MathContext mc10 = new MathContext(10, RoundingMode.HALF_UP);
MathContext mc30 = new MathContext(30, RoundingMode.DOWN);
MathContext mc40 = new MathContext(40, RoundingMode.HALF_UP);
MathContext mc60 = new MathContext(60, RoundingMode.DOWN);
System.out.println("MathContext(10, RoundingMode.HALF_UP)");
System.out.println();
x = new BigDecimal("400000005");
System.out.println("BigDecimal sqrt: " + x.sqrt(mc10));
System.out.println("BigDecimalMath sqrt: " + BigDecimalMath.sqrt(x, mc10));
System.out.println("Reference value: " + BigDecimalMath.sqrt(x, mc30) + "...");
System.out.println();
x = new BigDecimal("63999999");
System.out.println("BigDecimal sqrt: " + x.sqrt(mc10));
System.out.println("BigDecimalMath sqrt: " + BigDecimalMath.sqrt(x, mc10));
System.out.println("Reference value: " + BigDecimalMath.sqrt(x, mc30) + "...");
System.out.println();
System.out.println("MathContext(40, RoundingMode.HALF_UP)");
System.out.println();
x = new BigDecimal("1000000000001");
System.out.println("BigDecimal sqrt: " + x.sqrt(mc40));
System.out.println("BigDecimalMath sqrt: " + BigDecimalMath.sqrt(x, mc40));
System.out.println("Reference value: " + BigDecimalMath.sqrt(x, mc60) + "...");
System.out.println();
MathContext(10, RoundingMode.HALF_UP)
BigDecimal sqrt: 20000.00012
BigDecimalMath sqrt: 20000.00013
Reference value: 20000.0001249999996093750024414...
BigDecimal sqrt: 7999.999937
BigDecimalMath sqrt: 7999.999938
Reference value: 7999.99993749999975585937309265...
MathContext(40, RoundingMode.HALF_UP)
BigDecimal sqrt: 1000000.000000499999999999875000000000062
BigDecimalMath sqrt: 1000000.000000499999999999875000000000063
Reference value: 1000000.00000049999999999987500000000006249999999996093750000...
gradle.build
uploadArtifacts
in gradle.build
./gradlew uploadArtifacts
Close
own RepositoryRefresh
Release
own Repositorytemplate_release_note.md
build.gradle
of big-math
subproject./gradlew clean
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
until Release
becomes enabledRelease
own Repositorydocs/javadoc
docs/index.md
build.gradle
to use new release librarysettings.gradle
to add new regression project./run_regression_analysis.sh
Current Java implementation has O(n^2) complexity.
Possible solution for big n would be using of divide and conquer approach, as described here
Testing sqrt(43.79427225801566) precision=16
org.junit.ComparisonFailure: sqrt(43.79427225801566) referencePrecision=52 referenceResult=6.617724099568949240405337783925811044273632875494401
Expected :6.617724099568949
Actual :6.617724099568950
I'm currently working on using your excellent library for my EvalEx project.
While porting the acos() function, I came to some kind of rounding problems, I guess.
Given this code:
MathContext mathContext = new MathContext(68, RoundingMode.HALF_EVEN);
BigDecimal x = new BigDecimal("1", mathContext);
BigDecimal acos = BigDecimalMath.acos(x, mathContext);
System.out.println(acos.toPlainString());
it will not print 0 as expected, but it prints out 0.0000000000000000000000000000000000000000000000000000000000000000000000001
This only happens, when I use a scale >= 60 in the MathContext.
Is this a problem of big-math or BigDecimal?
Similar to BigDecimal.round()
but filling with trailing zeroes if appropriate.
See BigDecimalMath.factorial(BigDecimal, MathContext)
and BigDecimalMath.gamma(BigDecimal, MathContext)
and reimplement using BigComplex
.
Java9 finally has a sqrt()
function.
Analyze it and compare with BigDecimalMath.sqrt()
.
template_release_note.md
build.gradle
of big-math
subproject./gradlew clean
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
until Release
becomes enabledRelease
own Repositorydocs/javadoc
(copy folder javadoc
from build/docs
and renamed to e.g. v1.2.3
)docs/index.md
build.gradle
to use new release librarysettings.gradle
to add new regression project./run_regression_analysis.sh
The java.math.BigDecimal.equals() method compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).
Use split
and recursion
routines with cached BigInteger
values for first 100 values.
Hello,
I have experienced nullpointer exeption in SeriesCalculator 121 line, because factor of index 15 was not found...
Java version jre_8u201
SeriesCalculator BigDecimal calculate(BigDecimal x, MathContext mathContext)
method was receiving these parameters:
BigDecimal x = 0.00027737357367408531168137439716441660398990660211765625
MathContext mathContext = new MathContext(66, RoundingMode.HALF_EVEN)
Factor array had 17 elements, and was trying to get 15th element, but it was null. Image is attached of formed factors array.
Your library was used with this enpoint:
BigDecimal irr = new BigDecimal("1.0735999999999999999999999808121954095390385925")
BigDecimal numberOfParts = new BigDecimal("12.16666666666666666666666666666667");
BigDecimalMath.pow(irr, numberOfParts, DECIMAL128)
I cannot replicate this situation in tests locally... It is so strange... Locally using openjdk 1.8.0_201
Thank you.
In release 2.0.0 the calculation precision was improved at the cost of calculation performance.
Optimize performance of log()
without sacrificing calculation precision.
BigFloat should consider handling NaN, +INF, -INF
especially if coming from double
template_release_note.md
build.gradle
./gradlew clean
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
until Release
becomes enabledRelease
own Repositorydocs/javadoc
docs/index.md
build.gradle
to use new release librarysettings.gradle
to add new regression project./run_regression_analysis.sh
The BigDecimalMath.pow()
method is relying on Exception handling to recover from some corner cases.
In my profiling the BigDecimal.longValueExcact()
can throw ArithmeticException("Rounding necessary")
which takes a large chunk of the BigDecimalMath.pow()
execution time. The time is X axis on the flame graph below - roughly 50%?
The issue seem to be with try/catch code below and I wonder if the exception could be mitigated with some conditions inside try/catch to avoid some common cases of the ArithmeticException
?
-In terms of base 10 positive intetgers, is there a maximum positive integer that your library can load into memory and operate with?
-In terms of base 10 positive decimals (only), is there a minimum minute value that your library can load into memory and operate with?
-Full completion of the project Valhalla for Java along with OpenJDK promises value types and primitive types. I have gathered that it is possible to set up mathematics with the big-math library so that every operation does not require the precision to be submitted along as well, but that can be managed from one place within scope before the beginning of mathematics. If Valhalla allows operator inclusion with its new primitive types and other new advantages, are the big-math project developers likely going to be persuaded to incorporated into big-math? Operators like +,-,*, both modes of /, %, i++, i--, --i, ++i, +=, -=, *=, /= both modes, %= ?
java.lang.NumberFormatException
at java.math.BigDecimal.<init>(BigDecimal.java:494)
at java.math.BigDecimal.<init>(BigDecimal.java:383)
at java.math.BigDecimal.<init>(BigDecimal.java:806)
at java.math.BigDecimal.valueOf(BigDecimal.java:1274)
at ch.obermuhlner.math.big.BigDecimalMath.logUsingNewton(BigDecimalMath.java:525)
at ch.obermuhlner.math.big.BigDecimalMath.log(BigDecimalMath.java:478)
Thanks for a great library.
Testing with OpenJDK 11 and 15, BigDecimalMath.sqrt
seems to go into an infinite loop when passed any of these values when the precision and rounding mode are as follows:
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
System.out.println("Testing...");
System.out.println( BigDecimalMath.sqrt( new BigDecimal("10000000000000005"), mc ) );
System.out.println( BigDecimalMath.sqrt( new BigDecimal("10000000000000006"), mc ) );
System.out.println( BigDecimalMath.sqrt( new BigDecimal("10000000000000007"), mc ) );
System.out.println( BigDecimalMath.sqrt( new BigDecimal("10000000000000008"), mc ) );
System.out.println( BigDecimalMath.sqrt( new BigDecimal("10000000000000009"), mc ) );
here is MathContext.UNLIMITED
public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP);
precision is zero then
public static BigDecimal pow(BigDecimal x, long y, MathContext mathContext) { MathContext mc = new MathContext(mathContext.getPrecision() + 10, mathContext.getRoundingMode());
it changed form Unlimited to 10 digits precision
maybe change it to
MathContext mc = new MathContext(mathContext.getPrecision()==0?65535/*<<some big number?*/:mathContext.getPrecision(), mathContext.getRoundingMode());
maybe
if(mathContext.getPrecision()==0) throw new UnsupportedOperationException("Unlimited MathContext is not supported");
This is some kind of library! good stuff.
I have a question about having representation of following Double only related JDK functions:
I have especially problem with positive_infinite representation in BigDecimal...
What do you think to add this constant from Double into your library as method with mathcontext as additional parameter for precision config.
gradle.build
uploadArchives
in gradle.build
./gradlew uploadArchives
Close
own RepositoryRefresh
Release
own RepositoryHey, i'm working on a project and got in a situation where a i need the log function over a BigDecimal, found your project and seems great you have done a excellent work, but the limitation for me is that i can only add dependencies which are in a Maven repository, it would be great if you could publish it even if is in a beta stage, Thank you! and keep the good work!.
integralPart.intValue() does not give correct result in that case
With integralPart.longValueExact() you can fix this specific case e.g.
build.gradle
uploadArtifacts
in build.gradle
./gradlew :ch.obermuhlner.math.big:uploadArchives
Close
own RepositoryRefresh
Release
own Repositorydocs/javadoc
docs/index.md
The MANIFEST.MF must contain the necessary OSGi headers
Support temporary local MathContext
in DefaultBigDecimalMath
by pushing MathContext
on a thread local stack.
Copy paste from blog comment:
At the moment, BigDecimalMath requires you to submit a java.math.MathContext
every single time. Is it possible for you to add the option to omit that,
or have the situation so that users might submit or overwrite a MAthContext
once at the beginning, and include only the number parameters for the functions
inside BigDecimalMath?
I noticed that using the 2.3.1 things like this happen:
BigDecimal pow = BigDecimalMath.pow(new BigDecimal("200"), new BigDecimal("-200"), new MathContext(6));
System.out.println("" + pow);
prints 0
, which would obviously be a bug. I thought I'd look into it, and it costed me some time, but the code which is on maven central as 2.3.1 for this class doesn't seem to be right.
E.g. thispow
function ends with
return roundAbsolutePrecision(result, mathContext);
(which btw seems to cause the problem)
which I can't even find in the repository.
I don't know what happened, but something seems to be rather odd?
-I can see where to to obtain the javadoc for big-math,
Where can I find a free .jar build use file for for the latest
stable version of the big-math library that will work
with Java OpenJDK 19?
Add BigDecimalMath.reciprocal(BigDecimal, MathContext)
.
What is the license for your code?
build.gradle
uploadArtifacts
in build.gradle
./gradlew clean
./gradlew :ch.obermuhlner.math.big:uploadArchives
uploadArtifacts
in build.gradle
Close
own RepositoryRefresh
until Release
becomes enabledRelease
own Repositorydocs/javadoc
docs/index.md
Use reverse domain name convention
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.