0

Trying to figure out the best place to put a try catch statement when a recursive call is placed. The factorial computation is done with long datatype. Expecting an exception to be thrown when the factorial becomes too huge to fit into a long variable.

However the code is showing factorial = 0 whenever it's too large. No exception is being thrown. So is there a problem with the try-catch placement or does putting over-large numbers throw no exception?

class Fact
{
    static long fact(long n)
    {
       if(n==1)
           return 1;
        return n*fact(n-1);
    }

public static void main(String args[])
{
    try{
        long f = fact(555);
        System.out.println("Factorial = "+f);
    }
    catch(Exception e){
            System.out.println("Exception = "+e);
    }
}
}
AruniRC
  • 5,070
  • 7
  • 43
  • 73
  • See http://stackoverflow.com/questions/3001836/how-does-java-handle-integer-underflows-and-overflows-and-how-would-you-check-for – BlackJack Sep 20 '11 at 14:40
  • 1
    How does this code compile? the method long only returns a value when n equals. – leifg Sep 20 '11 at 14:42
  • sorry everybody i'd somehow missed out part of the code when pasting it into SO. it's added now. – AruniRC Sep 20 '11 at 14:46

3 Answers3

2

Integer overflow doesn't throw any exceptions in Java. Integer divide by zero throws ArithmeticException, but not overflow.

The question has now morphed into "Why does this return zero?" And the answer is that it's just a coincidence. If you modify the function like this:

static long fact(long n)
{
   if(n==1)
       return 1;
    long result =  n*fact(n-1);
    System.out.println(n + ", " + result);
    return result;
}

and then look at the output, you get (I deleted some lines in the middle and at the end):

2, 2
3, 6
4, 24
5, 120
6, 720
7, 5040
8, 40320
...
19, 121645100408832000
20, 2432902008176640000
21, -4249290049419214848
...
60, -8718968878589280256
61, 3098476543630901248
62, 7638104968020361216
63, 1585267068834414592
64, -9223372036854775808
65, -9223372036854775808
66, 0
67, 0
...

and then once it's hit zero, it's zero ever after. After bouncing around and overflowing a few times, your product just accidentally hits a number with 0s in the least significant 64 bits. Strange, but true.

Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • so something like if n exceeds `Integer.MAX_SIZE`anytime then the program would have to explicitly throw an exception. And if there's an overflow, then the type wraps around, something like (value)mod MAX_SIZE. Here the output is 0 always. – AruniRC Sep 20 '11 at 14:57
  • thanks, it's clear now. and questions might morph given inputs from answers that makes the actual problem clearer. – AruniRC Sep 23 '11 at 11:46
0
static long fact(long n) throws Exception
    {
       if (//when you want to throw exception){
           throw new Exception();
       }
       if(n==1)
           return 1;
    }

If you want to throw such an exception you should manually throw it. And by the way, fact is not recursive at all and won't do what you are expecting.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
0

The code, as written, will always return 1. I'm sure that you mean to have an else block with return n*fact(n-1), but I don't see it.

You probably overflowed long. I'd recommend that you not calculate factorials this way. Better to code using the gamma function and doubles:

http://mathworld.wolfram.com/GammaFunction.html

duffymo
  • 305,152
  • 44
  • 369
  • 561