Win a copy of TDD for a Shopping Website LiveProject this week in the Testing forum!

Frank Stalone

Greenhorn
since Sep 15, 2011
Cows and Likes
Cows
0
In last 30 days
0
Total given
0
Likes
0
0
Total given
0
Given in last 30 days
0
Scavenger Hunt
Ranch Hand Scavenger Hunt
Greenhorn Scavenger Hunt

Recent posts by Frank Stalone

Using lrdev's implementation.

Aha, it didn't occur to me that it would be more precise converting from String than from double. Lrdev's bigrational does have a constructor accepting a string as its parameter, as well as a method valueOf(String). I tried "0.45" and it returned 9/20 as desired.

Thanks.

Wasn't for an assignment btw. I just like having calculations in exact form.
10 years ago
Anyone use BigRationals? Is there a way to make them correctly convert decimals to fractions, getting around the limitations of ieee754?

For instance 0.45 should be 9/20, not 8106479329266893/18014398509481984
10 years ago
Oh, yeah you're right. Instead of changing some digits I should have just tried with more digits. I did that now, made a bigdecimal e with lots of digits and now the subfactorial method gets the right answers.

It should have been obvious, the inaccuracy was happening on the 17th digit.
10 years ago
So I was noticing imprecision with division of large numbers, and have concluded by process of elimination that it stems from the divide() method. Would it be possible to fix the method to make it accurate to more sig figs? Or is there an inevitable reason for the shortcoming?

What made me notice it was calculating derangements (aka subfactorials). I used the asymptotic formula !n = n!/e. I have a method for factorials that returns a BigInteger. I initialized a BigDecimal from the BigInteger, then divided it by Math.E. When it got a slightly wrong answer I increased the precision to a few thousand, but that got the same answer. I thought maybe E didn't have enough sig figs, so I tried changing some of the last digits to see if that would make the answer more wrong. It didn't. So I'm thinking the problem resides in the divide() method itself.

It's wrong when n>=19.

For n=19 the last two digits of the integer part should be 06 or 05 (the number has to round to an integer ending in 06, shown here: http://www.wolframalpha.com/input/?i=!19). Instead they're 09 and the decimal part begins with 922 so the integer part rounds to 10.

My derangement method isn't important, I'm just curious about this for when I use BigDecimals in the future. I don't see the point in BigDecimal division if divide() isn't more precise than dividing two doubles together. Nor the point in allowing the user to set the precision so high, when all the digits are gonna be wrong anyway.

Thanks for any light you can shed.
10 years ago