-2

I try to use a recursive function to calculate the Euler number in Java. It's OK when I enter small numbers into this formula:

enter image description here

But when I try to enter a bigger number like 1000 I get infinity. Why it's happening. How I can fix it.

import java.util.Scanner;

public class enumber {
    public static long fact(int a) {
         if(a <= 1) {
             return 1;
         }
         return a * fact(a - 1);
    }

    public static double calculate(int i) {
        double cresult = Math.pow(fact(i), -1);
        if(i == 0 ) {
            return 1;
        }
        return cresult+calculate(i-1);
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);  
        System.out.println("Enter i value: ");
        int i = sc.nextInt();
        double eresult = calculate(i);
        System.out.println(eresult);
    }
}
 

output;

    Enter i value: 
    1000
    Infinity
Abra
  • 19,142
  • 7
  • 29
  • 41
  • The top limit is 65 when I enter 66 I get infinity. – Muhammed Mustafa Savar Dec 21 '20 at 18:55
  • because you can't store a number that big in a double type using floating point math. – OldProgrammer Dec 21 '20 at 18:59
  • `Float`s and `Double`s follow a [Saturation arithmetic](https://en.wikipedia.org/wiki/Saturation_arithmetic#:~:text=Saturation%20arithmetic%20is%20a%20version,a%20minimum%20and%20maximum%20value.), i.e. if the numbers get too large, they are set to infinity. – Turing85 Dec 21 '20 at 19:00

3 Answers3

2

That's because you try to calculate the factorial of 1000....which is pretty huge. Factorial 1000

You try to store it in a long value, but long's max value is way smaller than 1000!. It basically doesn't fit anymore.

Consider using the class BigInteger (or BigDecimal), its in the default java sdk and you can directly output via println().

However you know the result already, its e, so you might only need to implement the Big-Class for the factorial.

Zacki
  • 177
  • 11
  • It would need to be BigDecimal, of course. – Neil Coffey Dec 21 '20 at 20:53
  • Im am not too sure if the BigDecimal is capable of holding 1000!, but sure the euler number cant be displayed as such a BigInteger – Zacki Dec 21 '20 at 21:26
  • Well, both will essentially store to a magnitude that memory will allow, and you'll need BigDecimal once you do the division Must admit, I didn't bother calculating whether specifically the value 1000! will exceed typical memory-- maybe it will, but I suppose I'm seeing the question essentially as "how do you calculate with more terms/accuracy than will fit in a double" rather than specifically being about the number 1000. – Neil Coffey Dec 21 '20 at 22:10
  • 1000! won't exceed typical memory as it only has 2568 digits and computes very fast. But I would not recalculate it each time. Just don't use recursion. Start at 1 and use that value, then divide that by 2, then by 3, then by 4. So each successive term in the computation only has 1 additional division. – WJS Dec 21 '20 at 22:28
  • I know, i wrote a whole program with factorials. But Java retired for me and i go on with C++ because it 's 30 times faster with ```100,000,000!``` – Zacki Dec 21 '20 at 22:48
1

You are exceeding the capacity of a long. But I would suggest you decide how much precision you want for e.

Let's say you want it to have an error of less than .0000001. Continue the iteration for e until the positive delta between your latest computation and the previous is less than or equal to your error.

If you want to take it to extremes, you can always use BigDecimal to increase the accuracy of your results.

WJS
  • 36,363
  • 4
  • 24
  • 39
0

I solved that problem by using loops. And for the old algorithm, I changed the fact method type to double. I get rid of Infinity. After that, I face "StackOverflowError". What is a StackOverflowError?

My new algorithm is;

import java.util.Scanner;

public class enumber2 {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        double fact;
        double eNumber = 0;
        int i = in.nextInt();
        
        while(i>0) {
            fact=1;
            for(int j=1; j<=i; j++) {
                fact = fact * j;
            }
            eNumber = eNumber +(1.0/fact);
            i--;
        }
        eNumber = eNumber +1;
        System.out.println(eNumber);
    }

}

even I enter big numbers after a little bit of patient I'm getting results without exception.