tags:

views:

119

answers:

4

Hi

I'm wondering how could I anticipate whether the next iteration will generate an integer overflow while calculating the factorial F or not?

Let's say that at each iteration I have an int I and the maximum value is MAX_INT.

It sounds like a homework, I know. It's not. It's just me asking myself "stupid" questions.

Addendum

I though about, given a number of BITS (the width an integer can take, in bits), I could round up the number I to the next power of two, and detect if a shift to left would exceed BITS. But how would that look like, algorithmically?

+4  A: 

Factorials are a series of multiplications, and the number of bits needed to hold the result of a multiplication is the sum of the bits of the two multiplicands. So, keep a running total of how many bits are used in your result, and the current number of bits needed to hold the value you are multiplying in. When that's greater than the number of bits left, you're about to overflow.

swestrup
I'll chew on it, but I'll accept KennyTM's answer, since it's more intuitive, mathematically. @SO users: please vote this one, it's a cool answer!
Flavius
...but this is only very roughly: example: 2*2*2*2 = 16 multiplication of 4 values, 2 bits each, results in a 4 bit value, but 3*3*3*3 = 81, also a multiplication of 4 values, 2 bits each, results in a 6 bit value. The solution of Moron is more accurate.
Curd
Implementing this naively will tend to cause you to underestimate when you're going to overflow. Factorial goes from just fine to overflow in large step at the very end of the multiplication, so this will only really get you into trouble when the last factorial before overflow is near MAX_INT, but it can. 4 takes 3 bits to represent and 3 takes 2, but 12 only takes 4 bits to represent, not 5.
Omnifarious
+6  A: 

Alternative hint:

a * b ≤ MAX_INT 

is equivalent to

a ≤ MAX_INT / b

if b > 0.

KennyTM
Duh! I can't imagine why this approach didn't occur to me!
swestrup
+2  A: 

If you've so far got m = (n-1)! and you're about to multiply by n, you can guard against overflow by checking that

   m <= MAX_INT / n
I. J. Kennedy
+1  A: 

You can probably use Stirling's Approximation formula which says that

ln (n!) = n*ln(n) - n + ln(2*pi*n)/2 + O(1/n)

and will be quite accurate.

You don't actually need to go about trying to multiply etc. Of course, this does not directly answer what you asked, but given that you are just curious, hope this helps.

Moron
+1 That's what I wanted to answer. And: the log of a value is proportional to the number of bits needed to represent the value. So this is quite what Flavius needs.
Curd
This was my first thought too, but I couldn't remember the name of the approximation formula. Stupidly enough, its the same as my name. :-/
swestrup