Reputation: 165
The statement I'm writing where values may overflow is as below:
fact = ((fact * (llu) (i - 1)) / (llu) (i - M)) % MOD;
llu Ans = (llu) C[k - 1] * fact;
Here llu
means unsigned long long
i
is a signed integer and varies between values ranging from 210 to 220
MOD
is 109 + 9
Variables fact
and Ans
are of type unsigned long long
.
M
is a signed integer and can be atmost as high as 210
C[k - 1]
is the (k - 1)
th index term of an int
array C
and is of order of 109
All values are always positive.
Question:
Now, regarding the type casting I've done in the above code (from int
to unsigned long long
); Is it fine enough to handle overflows or am I doing more/less/incorrect type casting?
Further, is it right to perform division by (i - M)
in the 1st line of my code or should it preferably be written as:
fact = fact * (llu) (i - 1);
fact = (fact / (llu) (i - M)) % MOD;
Upvotes: 0
Views: 653
Reputation: 771
You didnt define the limits of fact, since it's part of the first expression. If fact can initially be 2^60 for example then you have an overflow.
When you multiply integer bit values you need to sum the amount of bits. For example if you multiple two 32 bit values you will need/get 32+32 = 64bits.
fact=((fact*(llu)(i-1))/(llu)(i-M))%MOD;
In our example we have i up to 20 bits, it means that to avoid an overflow in the first expression fact must be at most Bitsof(unsigned long long)-20. If unsigned long long is 64 bit then fact can be up to 44 bits, e.g 2^44.
llu Ans=(llu)C[k-1]*fact;
In the second expression we have a similar situation, fact must be at most 64-30 bits (10^9 takes about 29 bits), after evaluating the first expression, which is verified by the %MOD expression. Fact will be less than 10^10 after first expression which is almost 32 bits.
Short answer: if fact is initially less than 2^44 then it will not overflow.
In such cases I prefer to use explicit integer sizes, for example type u_int64_t, I know it's unsigned 64 bit.
Upvotes: 1