Smarter than BigDecimal Class

L

Luc The Perverse

So you have to be smarter than the class that you're using. Apparently I
don't qualify.

So I have 3 BigIntegers and I need to divide them with high precision and
then convert them to doubles (in an array) and they need to be accurate to
within 1E-9.

My code was supposed to be very simple, but it kept rounding to whole
integers, even after I called the function setScale(40,
BigDecimal.ROUND_FLOOR) (Note: I tried EVERY variation of rounding
parameters including unnecessary, which as expected, threw an exception.)
Eventually I got the following convoluted mess to work. (mass, X and Y are
all BigInteger class instances with values from preceding code)

if(mass.equals(BigInteger.ZERO))
return new double[0]; //special case
BigDecimal massTimesTwo = new
BigDecimal(mass.multiply(BigInteger.valueOf(2))).add(BigDecimal.valueOf(1E-30));
massTimesTwo.setScale(40, BigDecimal.ROUND_FLOOR);
BigDecimal bdX = new BigDecimal(X).add(BigDecimal.valueOf(1E-30));
bdX.setScale(40, BigDecimal.ROUND_FLOOR);
BigDecimal bdY = new BigDecimal(Y).add(BigDecimal.valueOf(1E-30));
bdY.setScale(40, BigDecimal.ROUND_FLOOR);
double[] ret =
{
bdX.divide(massTimesTwo, BigDecimal.ROUND_UP).doubleValue(),
bdY.divide(massTimesTwo, BigDecimal.ROUND_UP ).doubleValue()
};
return ret;

I find it hard to believe that this mess is necessary :) Help?
 
P

Patricia Shanahan

Luc said:
So you have to be smarter than the class that you're using. Apparently I
don't qualify.

So I have 3 BigIntegers and I need to divide them with high precision and
then convert them to doubles (in an array) and they need to be accurate to
within 1E-9.

My code was supposed to be very simple, but it kept rounding to whole
integers, even after I called the function setScale(40,
BigDecimal.ROUND_FLOOR) (Note: I tried EVERY variation of rounding
parameters including unnecessary, which as expected, threw an exception.)
Eventually I got the following convoluted mess to work. (mass, X and Y are
all BigInteger class instances with values from preceding code)

if(mass.equals(BigInteger.ZERO))
return new double[0]; //special case
BigDecimal massTimesTwo = new
BigDecimal(mass.multiply(BigInteger.valueOf(2))).add(BigDecimal.valueOf(1E-30));
massTimesTwo.setScale(40, BigDecimal.ROUND_FLOOR);
BigDecimal bdX = new BigDecimal(X).add(BigDecimal.valueOf(1E-30));
bdX.setScale(40, BigDecimal.ROUND_FLOOR);

This seems suspicious to me. You call setScale, but do nothing with its
result.

I tried the following:

import java.math.BigDecimal;
public class TestBigDecimal {
public static void main(String[] args) {
BigDecimal x = new BigDecimal(20).setScale(20);
BigDecimal d = new BigDecimal(3);
System.out.println(x.divide(d, BigDecimal.ROUND_UP));
}
}

and got output:

6.66666666666666666667

Patricia
 
L

Luc The Perverse

Patricia Shanahan said:
This seems suspicious to me. You call setScale, but do nothing with its
result.
*snip example*

OOOOOOOOOOOOOOOH!!!!!!

setScale returns a new BigDecimal. I thought setScale was setting a
property in the existing BigDecimal. And hence the confusion ends.

Thank you!
 
M

Mark Space

Luc said:
So you have to be smarter than the class that you're using. Apparently I
don't qualify.

So I have 3 BigIntegers and I need to divide them with high precision and
then convert them to doubles (in an array) and they need to be accurate to
within 1E-9.


Just curious. What application requires this kind of precision? This is
far in excess of what I'd consider appropriate for scientific
applications. Is this some weird kind of financial app?
 
L

Luc The Perverse

Mark Space said:
Just curious. What application requires this kind of precision? This is
far in excess of what I'd consider appropriate for scientific
applications. Is this some weird kind of financial app?

Yet another top coder problem :)

It simply has to be the "right" answer, which the problem statement defines
to being within 1E-9 of the "true" value (presumably they calculate it to
greater precision than that. I was getting overflow when I was trying to
use regular doubles (in retrospect the imprecision may have been coming from
ints before they were turned to doubles, but I found it an excellent
opportunity to familiarize myself with the BigDecimal class. After all - if
I'm not learning anything, what is the point of doing all these practice
problems? hehe)
 
P

Patricia Shanahan

Luc said:
Yet another top coder problem :)

It simply has to be the "right" answer, which the problem statement defines
to being within 1E-9 of the "true" value (presumably they calculate it to
greater precision than that. I was getting overflow when I was trying to
use regular doubles (in retrospect the imprecision may have been coming from
ints before they were turned to doubles, but I found it an excellent
opportunity to familiarize myself with the BigDecimal class. After all - if
I'm not learning anything, what is the point of doing all these practice
problems? hehe)

Using BigDecimal would make sense to me if the integers are outside the
range that can be exactly converted to double. All Java int values are
in that range, but not all longs.

If the integers can be exactly converted to double, the result of doing
so, and then doing the decimal division is the closest double to the
infinite precision result of dividing the integers. You can't do better
than that and end up with a double result.

Patricia
 
P

Patricia Shanahan

Patricia said:
Using BigDecimal would make sense to me if the integers are outside the
range that can be exactly converted to double. All Java int values are
in that range, but not all longs.

If the integers can be exactly converted to double, the result of doing
so, and then doing the decimal division is the closest double to the

I meant to type "and then doing the double division"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top