Reputation: 861
I am want to calculate the value
X =n!/2^r
where n<10^6 and r<10^6
and it's guarantee that value of X is between O to 10
How to calculate X since i can't simple divide the factorial and power term since they overflow the long integer.
My Approach
Do with the help of Modulus. Let take a prime number greater than 10 let say 101
X= [(Factorial N%101)*inverse Modulo of(2^r)]%101;
Note that inverse modulo can easily be calculate and 2^r%101 can also be calculated.
Problem:
It's not guarantee that X is always be integer it can be float also.
My method works fine when X is integer ? How to deal when X is a floating point number
Upvotes: 1
Views: 118
Reputation:
An approach that would be tunable for precision/performance would be the following:
Store the factorial in an integer with a fixed number of bits. We can drop the last few digits if the number gets too large, since they won't affect the overall result altogether that much. By scaling this integer larger/smaller the algorithm gets tunable for either performance or precision.
Whenever the integer would overflow due to multiplication, shift it to the right by a few places and subtract that value from r
. In the end there should be a small number left as r
and an integer v
with the most significant bits of the factorial. This v
can now be interpreted as a fixed-point number with r
fractional digits.
Depending upon the required precision this approach might even work with long
, though I haven't had the time to test this approach yet apart from a bit experimenting with a calculator.
Upvotes: 0
Reputation: 4431
Except for a very few cases (with small n and r) X will not be an integer -- for if n >= 11 then 11 divides n! but doesn't divide any power of two, so if X were integral it would have to be at least 11.
One method would be: initialise X to one; then loop: if X > 10 divide by 2 till its not; if X < 10 multiply by the next factors till its not; until you run out of factors and powers of 2.
Upvotes: 0
Reputation: 65498
If approximate results are OK and you have access to a math library with base-2 exponential (exp2
in C), natural log gamma (lgamma
in C), and natural log (log
in C), then you can do
exp2(lgamma(n+1)/log(2) - r).
Upvotes: 1
Reputation: 43487
Find the power that 2
appears at in n!
. This is:
P = n / 2 + n / 2^2 + n / 2^3 + ...
Using integer division until you reach a 0
result.
If P >= r
, then you have an integer result. You can find this result by computing the factorial such that you ignore r
powers of 2
. Something like:
factorial = 1
for i = 2 to n:
factor = i
while factor % 2 == 0 and r != 0:
factor /= 2
r -= 1
factorial *= factor
If P < r
, set r = P
, apply the same algorithm and divide the result by 2^(initial_r - P)
in the end.
Upvotes: 0