0

I'm trying to calculate Euler's number to a high degree of accuracy using BigDecimals but after a while, the numbers get so small that the JVM throws a divide-by-0 error. Any ideas on how to overcome? I find that the try-catch block is always called after exactly 34 iterations of the division, but I don't know why. The formula for Euler's number is an infinite series, so 34 iterations gets it close to the actual value of e, but not as accurate as I'd like it. It's not actually dividing by 0, but it's probably too small for the JVM to tell the difference.

    BigDecimal ee = BigDecimal.ZERO;
    for (int k = 0; k < 50; k++) {
        int fact = factorial(k);
        try {
            BigDecimal trial = BigDecimal.ONE.divide(BigDecimal.valueOf(fact), 100, RoundingMode.CEILING);
        } catch (Exception e) {
            System.out.println("---- Div-by-0 error; Iterated " + k + " times ----");
            break;
        }
        ee = ee.add(BigDecimal.ONE.divide(BigDecimal.valueOf(fact), 100, RoundingMode.CEILING));
    }
    System.out.println("\n---- Final: \t\te = " + power(ee, x));
}
Ryhun
  • 3
  • 1
  • 4
  • 2
    It's probably because it's actually dividing by zero. `fact` is going to overflow, and creating a `BigDecimal` after that still won't have the correct value. – azurefrog Oct 16 '19 at 19:40
  • factorial(49) is 6.0828186e+62. That's way way more than the maximum value of an int. – JB Nizet Oct 16 '19 at 19:41

2 Answers2

2

Your factorial calculations are overflowing. Your factorial method must be returning int because you've assigned the return value of that method to int.

Starting with 13 the overflow occurs. 13! is 6,227,020,800‬, the first factorial value too large to be represented in an int. Overflow represents this value as 1932053504. The problem gets worse as additional values become negative, e.g. 17! is calculated as -288522240.

Eventually, enough factors of 2 accumulate in the product that all 1 bits get shifted off the end, leaving 0 (starting at 34!). This is what caused your division by zero error.

But that is just a symptom of overflow that already occurred much earlier. Use BigDecimal for your factorial calculation to avoid overflow and maintain precision. That BigDecimal can be passed directly to divide without conversion.

rgettman
  • 176,041
  • 30
  • 275
  • 357
0

I don't think you are using correct datatypes to store values. Use BigInteger as it can store up to 100! value in it.

Int max values: int 4 bytes -2,147,483,648 to 2,147,483,647.

Since you are assigning the value higher than the limit, it will loop back to negative and probably resulting into 0 at some point.

Values of factorial:

01! = 1 02! = 2 03! = 6 04! = 24 05! = 120 12! = 479001600

Max value of Int -- 2147483647

13! = 6227020800

nishant
  • 91
  • 6