I want to do the following in java:
Math.pow((int),(double))
and keep the decimal precision to more than 16 (much greater than that actually).
Is this possible? I know it involves using BigDecimal and maybe ln functions, but I'm not sure how to approach this.
Thanks in advance.
EDIT
The reason I am asking is because I am trying to compute pi to an enormous amount of precision. Currently, I am using Chudnovsky's algorithm. I've tried to use taylor series for this purpose and it takes much too long to be practical.
EDIT
Maybe this is a better question: How do you find the square root of a BigDecimal. (Technically, same as the original since raising to the .5 is...)
Related
I've got the task to calculate the golden ratio (phi = (1+ sqrt(5))/2).
But I need to calculate it with about 50 decimal digits / decimal places and then round the result up to 30 decimal digits and print it on the console. I am allowed to use BigDecimal and MathContext.
Does anyone have an idea how to calculate it? I am lost right now.
Thanks
I won't try to solve your problem for you!
However I think to point you in a promising direction would be to look at the API:
https://docs.oracle.com/javase/9/docs/api/java/math/BigDecimal.html
and specifically at the constructor:
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)
I believe that if you experiment with these objects you can meet your goal.
Note: sqrt was only added to BigDecimal in Java 9.
Good luck.
I found this on the web. It can be used to verify your calculations.
String goldenRatio =
"1.61803398874989484820458683436563811772030917980576286213544862270526046281890" +
"244970720720418939113748475408807538689175212663386222353693179318006076672635";
You can verify the correctness of a regular calculation by
Verifying the length (don't forget the decimal point and the whole number digits).
verifying that it matches some initial part of the supplied answer.
To calculate normally, I used MathContext of precision = 30 and RoundingMode.HALF_UP.
This may not work for the way you are expected to do it. If you run into problems, folks here will be able to help.
I strongly suggest you post an attempt before asking for any additional help though.
I'm using Math.sin to calculate trigonometry in Java with 3 decimal precision. However when I calculate values that should result in an Integer I get 1.0000000002 instead of 1.
I have tried using
System.out.printf(Locale.ROOT, "%.3f ", v);
which does solve the problem of 1.000000002 turning into 1.000.
However when I calculate numbers that should result in 0 and instead get -1.8369701987210297E-16 and use
System.out.printf(Locale.ROOT, "%.3f ", v);
prints out -0.000 when I need it to be 0.000.
Any ideas on how to get rid of that negative sign?
Lets start with this:
How do I avoid rounding errors with doubles?
Basically, you can't. They are inherent to numerical calculations using floating point types. Trust me ... or take the time to read this article:
What every Computer Scientist should know about floating-point arithmetic by David Goldberg.
In this case, the other thing that comes into play is that trigonometric functions are implemented by computing a finite number of steps of an infinite series with finite precision (i.e. floating point) arithmetic. The javadoc for the Math class leaves some "wiggle room" on the accuracy of the math functions. It is worth reading the javadocs to understand the expected error bounds.
Finally, if you are computing (for example) sin π/2 you need to consider how accurate your representation of π/2 is.
So what you should really be asking is how to deal with the rounding error that unavoidably happens.
In this case, you are asking is how to make it look like the user of your program as if there isn't any rounding error. There are two approaches to this:
Leave it alone! The rounding errors occur, so we should not lie to the users about it. It is better to educate them. (Honestly, this is high school maths, and even "the pointy haired boss" should understand that arithmetic is inexact.)
Routines like printf do a pretty good job. And the -0.000 displayed in this case is actually a truthful answer. It means that the computed answer rounds to zero to 3 decimal places but is actually negative. This is not actually hard for someone with high school maths to understand. If you explain it.
Lie. Fake it. Put in some special case code to explicitly convert numbers between -0.0005 and zero to exactly zero. The code suggested in a comment
System.out.printf(Locale.ROOT, "%.3f ", Math.round(v * 1000d) / 1000d);
is another way to do the job. But the risk of this is that the lie could be dangerous in some circumstances. On the other hand, you could say that real mistake problem is displaying the numbers to 3 decimal places.
Depends on accuracy you need, you can multiply by X and divide by X where X is X=10^y and y is required floating poing precision.
So, I came across a problem today in my construction of a restricted Boltzmann machine that should be trivial, but seems to be troublingly difficult. Basically I'm initializing 2k values to random doubles between 0 and 1.
What I would like to do is calculate the geometric mean of this data set. The problem I'm running into is that since the data set is so long, multiplying everything together will always result in zero, and doing the proper root at every step will just rail to 1.
I could potentially chunk the list up, but I think that's really gross. Any ideas on how to do this in an elegant way?
In theory I would like to extend my current RBM code to have closer to 15k+ entries, and be able to run the RBM across multiple threads. Sadly this rules out apache commons math (geometric mean method is not synchronized), longs.
Wow, using a big decimal type is way overkill!
Just take the logarithm of everything, find the arithmetic mean, and then exponentiate.
Mehrdad's logarithm solution certainly works. You can do it faster (and possibly more accurately), though:
Compute the sum of the exponents of the numbers, say S.
Slam all of the exponents to zero so that each number is between 1/2 and 1.
Group the numbers into bunches of at most 1000.
For each group, compute the product of the numbers. This will not underflow.
Add the exponent of the product to S and slam the exponent to zero.
You now have about 1/1000 as many numbers. Repeat steps 2 and 3 unless you only have one number.
Call the one remaining number T. The geometric mean is T1/N 2S/N, where N is the size of the input.
It looks like after a sufficient number of multiplications the double precision is not sufficient anymore. Too many leading zeros, if you will.
The wiki page on arbitrary precision arithmetic shows a few ways to deal with the problem. In Java, BigDecimal seems the way to go, though at the expense of speed.
Just a day before I participated in the qualification round of Google Code Jam. This is my first experience of such an online coding contest. It was really fun.
There were three problems given of which i was able to solve two. But on one of the problems I was asked to work with values that are really huge. I am a Java guy and I thought I would go for double variable. Unfortunately, the precision of double also was not enough. Moreover, I attended this during the closing stage, I was not having the time to dig much into it (plus solving 1 is enough to qualify to the next stage).
My question is this, How to have a precision mechanism that is greater than double. My coding experience is in Java, so it would be great if you could please answer in that lines.
Thanks
Java has BigDecimall for arbitrary-precision arithmetic - but it's much, much slower than using double.
It's also possible that the problem in question was supposed to be soved by using algebraic transformations and e.g. work with logarithms.
If the problem requires integers you can use BigInteger.
Also, long is slightly better than double for integers, with 63 bits compared to 53 bits of precision (assuming positive numbers).
You can use arbitrary precision numbers, such as BigDecimal - it's slower but as precise as you specify.
Im facing a scenario where in ill have to compute some huge math expressions. The expressions in themselves are simple, ie have just the conventional BODMAS fundamental but the numbers that occur as operands are very large, to the tune of 1000 digit numbers. I do know of the BigInteger class of the java.math module but am looking for a different way so that the computation can occur also in a speedy manner. Im a guy still finding his feet in Java, so any pointers or advice in gthis regard would be of great help.
Regards
p1nG
Try it with BigInteger, profile the results with some test calculations, and see if it will work for you, before you look for something more optimized.
Since you say you are new to Java, I would have to suggest you use BigInteger and BigDecimal unless you want to write your own arbitrarily large number handlers. BigInteger and BigDecimal are fast enough for most uses of them. The only time I've had speed issues with them is when dealing with numbers on the order of a million digits.
That is unless you have a specific need for not using BigInteger.
First write the program correctly (using BigFoo) and then determine if optimization is appropriate.
BigInteger/BigFloat will be the most optimized implementation of generalized math that you will possibly get.
If you want it faster, you MIGHT be able to write assembly to use bit-shifting patters for specialized math (well, like divide by 2 tends to be a simple right shift), but if you are doing more than a few different types of equations, that will be very impractical.
BigInteger is only slow in comparison to int, but it will probably be the best you are going to possibly get for operations on numbers of more than 64 bits or so without going to another language--and even then you probably won't get much of an improvement unless that other language is assembly...
I am surprised that equations with 1000 digits have a practical application (except perhaps encryption)
Could you could explain what you are doing and what your speed requirements are?