Frank Stalone

Greenhorn

Posts: 4

posted 6 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.

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.

posted 6 years ago

But it

Frank Stalone wrote: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.

But it

*doesn't*have enough sig figs. It's a double, after all, so that means it only has about 16. And 19! is on the order of 10^17, so you could expect errors to creep into the units digit in that case.

Frank Stalone

Greenhorn

Posts: 4

posted 6 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.

It should have been obvious, the inaccuracy was happening on the 17th digit.