calculating factorial of large numbers in 0.5 second with python - python

I've been trying to find a super fast code that can calculate the factorial of a big number like 70000 in 0.5 second,My own code could do it in 10 seconds.I've searched everywhere, every code I find has memory error problem or is not as fast as I want. Can anyone help me with this?
enter code here
import math
num =int(raw_input())
usefrm=0
if len(str(num)) > 2:
if int(str(num)[-2]) % 2 == 0:
usefrm = 'even'
else:
usefrm = 'odd'
else:
if num % 2 == 0:
usefrm = 'even1'
else:
usefrm = 'odd1'
def picknumber(num):
s = str(math.factorial(num))
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
def picknumber1(num):
s = str(num)
l = []
for n in s:
if int(n) != 0:
l.append(int(n))
return l[-1]
if usefrm == 'even':
e=picknumber1(6*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
if usefrm == 'odd':
e=picknumber1(4*picknumber(int(num/5))*picknumber(int(str(num)[-1])))
else:
e=picknumber1(math.factorial(num))
print e

For most practical use, the Stirling's approximation is very fast and quite accurate
import math
from decimal import Decimal
def fact(n):
d = Decimal(n)
return (Decimal(2 * math.pi) * d).sqrt() * (d / Decimal(math.e)) ** d
print(fact(70000))
1.176811014417743803074731978E+308759

Try to use the commutativity property of integer multiplication.
When multiplied numbers are long (they do not fit in a single word), the time necessary to perform the operation grows superlinearly with their length.
If you multiply the smallest (shortest in terms of memory representation) factors (and partial products) first, you may save a lot of time.

You may use math.factorial(). For example:
from math import factorial
factorial(7000)
with execution time of 20.5 msec for calculating the factorial of 7000:
python -m timeit -c "from math import factorial; factorial(7000)"
10 loops, best of 3: 20.5 msec per loop

If you don't want a perfect precision, you can use the Stirling's approximation
https://en.wikipedia.org/wiki/Stirling's_approximation
import np
n! ~ np.sqrt(2*np.pi*n)*(n/np.e)**n
for large n values. This calculation is literally instantaneous.

Maybe you can try to make use of threads.

Related

Python: Streamlining Code for Brown Numbers

I was curious if any of you could come up with a more streamline version of code to calculate Brown numbers. as of the moment, this code can do ~650! before it moves to a crawl. Brown Numbers are calculated thought the equation n! + 1 = m**(2) Where M is an integer
brownNum = 8
import math
def squareNum(n):
x = n // 2
seen = set([x])
while x * x != n:
x = (x + (n // x)) // 2
if x in seen: return False
seen.add(x)
return True
while True:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
if squareNum(i) is True:
print("pass")
print(brownNum)
print(math.factorial(brownNum)+1)
break
else:
print(brownNum)
print(math.factorial(brownNum)+1)
brownNum = brownNum + 1
continue
break
print(input(" "))
Sorry, I don't understand the logic behind your code.
I don't understand why you calculate math.factorial(brownNum) 4 times with the same value of brownNum each time through the while True loop. And in the for loop:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
i will only take on the value of math.factorial(brownNum)+1
Anyway, here's my Python 3 code for a brute force search of Brown numbers. It quickly finds the only 3 known pairs, and then proceeds to test all the other numbers under 1000 in around 1.8 seconds on this 2GHz 32 bit machine. After that point you can see it slowing down (it hits 2000 around the 20 second mark) but it will chug along happily until the factorials get too large for your machine to hold.
I print progress information to stderr so that it can be separated from the Brown_number pair output. Also, stderr doesn't require flushing when you don't print a newline, unlike stdout (at least, it doesn't on Linux).
import sys
# Calculate the integer square root of `m` using Newton's method.
# Returns r: r**2 <= m < (r+1)**2
def int_sqrt(m):
if m <= 0:
return 0
n = m << 2
r = n >> (n.bit_length() // 2)
while True:
d = (n // r - r) >> 1
r += d
if -1 <= d <= 1:
break
return r >> 1
# Search for Browns numbers
fac = i = 1
while True:
if i % 100 == 0:
print('\r', i, file=sys.stderr, end='')
fac *= i
n = fac + 1
r = int_sqrt(n)
if r*r == n:
print('\nFound', i, r)
i += 1
You might want to:
pre calculate your square numbers, instead of testing for them on the fly
pre calculate your factorial for each loop iteration num_fac = math.factorial(brownNum) instead of multiple calls
implement your own, memoized, factorial
that should let you run to the hard limits of your machine
one optimization i would make would be to implement a 'wrapper' function around math.factorial that caches previous values of factorial so that as your brownNum increases, factorial doesn't have as much work to do. this is known as 'memoization' in computer science.
edit: found another SO answer with similar intention: Python: Is math.factorial memoized?
You should also initialize the square root more closely to the root.
e = int(math.log(n,4))
x = n//2**e
Because of 4**e <= n <= 4**(e+1) the square root will be between x/2 and x which should yield quadratic convergence of the Heron formula from the first iteration on.

Python: Division by larger numbers slower?

Why does dividing by the larger factor pair result in slower execution?
My solution for https://codility.com/programmers/task/min_perimeter_rectangle/
from math import sqrt, floor
# This fails the performance tests
def solution_slow(n):
x = int(sqrt(n))
for i in xrange(x, n+1):
if n % i == 0:
return 2*(i + n / i))
# This passes the performance tests
def solution_fast(n):
x = int(sqrt(n))
for i in xrange(x, 0, -1):
if n % i == 0:
return 2*(i + n / i)
It's not division that slows it down; it's the number of iterations required.
Let L = xrange(0, x) (order doesn't matter here) and R = xrange(x, n+1). Every factor of n in L can be paired with exactly one factor of n in R. In general, x is much, much smaller than n/2, so L is much smaller than R. This means that there are far more elements of R that don't divide n than there are in L. In the case of a prime number, there are no factors, so the slow solution has to check every value of the much larger than instead of the much smaller set.
That's obvious. The first function loops many more times.
Note that sqrt(n) != n - sqrt(n)! in general sqrt(n) << n-sqrt(n) where << means much lesser than.
If n=1000 the first function is looping 969 times while the second one only 32.
I'd say the of iterations is the key which makes perfomance a little bit different between your functions as #Bakuriu already said. Also, xrange could be slightly more expensive than using a simple loop, for instance, take a look f3 will perform a little better than f1 & f2:
import timeit
from math import sqrt, floor
def f1(n):
x = int(sqrt(n))
for i in xrange(x, n + 1):
if n % i == 0:
return 2 * (i + n / i)
def f2(n):
x = int(sqrt(n))
for i in xrange(x, 0, -1):
if n % i == 0:
return 2 * (i + n / i)
def f3(n):
x = int(sqrt(n))
while True:
if n % x == 0:
return 2 * (x + n / x)
x -= 1
N = 30
K = 100000
print("Measuring {0} times f1({1})={2}".format(
K, N, timeit.timeit('f1(N)', setup='from __main__ import f1, N', number=K)))
print("Measuring {0} times f1({1})={2}".format(
K, N, timeit.timeit('f2(N)', setup='from __main__ import f2, N', number=K)))
print("Measuring {0} times f1({1})={2}".format(
K, N, timeit.timeit('f3(N)', setup='from __main__ import f3, N', number=K)))
# Measuring 100000 times f1(30)=0.0738177938151
# Measuring 100000 times f1(30)=0.0753000788315
# Measuring 100000 times f1(30)=0.0503645315841
# [Finished in 0.3s]
Next time, you got these type of questions, using a profiler is highly recommended :)

Python 3 Project Euler Run Time

This is my solution to the Project Euler Problem 3:
def max_prime(x):
for i in range(2,x+1):
if x%i == 0:
a = i
x = x/i
return a
max_prime(600851475143)
It takes too much time to run. What's the problem?
There are several problems with your code:
If you're using Python 3.x, use // for integer division instead of / (which will return a float).
You solution doesn't account for the multiplicity of the prime factor. Take 24, whose factorization is 2*2*2*3. You need to divide x by 2 three times before trying the next number.
You don't need to try all the values up to the initial value of x. You can stop once x has reached 1 (you know you have reached the highest divisor at this point).
Once you solve these three problems, your solution will work fine.
==> projecteuler3.py
import eulerlib
def compute():
n = 600851475143
while True:
p = smallest_prime_factor(n)
if p < n:
n //= p
else:
return str(n)
# Returns the smallest factor of n, which is in the range [2, n]. The result is always prime.
def smallest_prime_factor(n):
assert n >= 2
for i in range(2, eulerlib.sqrt(n) + 1):
if n % i == 0:
return i
return n # n itself is prime
if __name__ == "__main__":
print(compute())
Your solution is trying to iterate up to 600851475143, which isn't necessary. You only need to iterate up to the square root of the largest prime factor.
from math import sqrt
def max_prime_factor(x):
i = 2
while i ** 2 <= x:
while x % i == 0: # factor out ALL multiples of i
x //= i
i += 1
return x
print(max_prime_factor(600851475143))

Project Euler 23: Why is my code so slow and what can I do to speed it up?

Here is a link to the problem: link. My code seems to be slowing down exponentially but I can't identify why or a more efficient algorithm. My approach was to identify all of the abundant numbers up to the limit and identify the numbers up to the upper limit that are not sums of the numbers by subtracting each number from the original and seeing if the difference is inside the abundant numbers list. Any ideas as to what is going on and or a better approach to this problem?
Here is the code that I used:
import numpy as np
import math
import itertools
def divisors(n): return sorted(np.unique(np.array([[x,n/x] for x in range(1,int(round(math.sqrt(n))+1)) if n%x == 0]).flatten()).tolist())[0:-1]
ubound = 28123
abundant_numbers = [x for x in range(1,ubound) if x < sum(divisors(x))]
def is_sum_of_abundant(n):
isob = False
for i in abundant_numbers:
if (n - i) <=0:
continue
else:
if (n - i) in abundant_numbers:
isob = True
return isob
s = 0
for x in range(1,ubound):
print "%.2f percent\n" % ((float(x)/ubound)*100)
if is_sum_of_abundant(x):
print "{} is abundant".format(x)
else:
s+=x
print "{} is not abundant".format(x)
print s
One thing you try is a better way to calculate the sum of the divisors - see the definition of the sigma function here. Essentially you find the prime factors and use the fact that
sigma(ab) = sigma(a) * sigma(b)
sigma(p^n) = (p^(n+1)-1)/(p-1)
where sigma(n) is the sum of the positive divisors.

Float Limit in Python

I was writing a program in python
import sys
def func(N, M):
if N == M:
return 0.00
else:
if M == 0:
return pow(2, N+1) - 2.00
else :
return 1.00 + (0.5)*func(N, M+1) + 0.5*func(N, 0)
def main(*args):
test_cases = int(raw_input())
while test_cases:
string = raw_input()
a = string.split(" ")
N = int(a[0])
M = int(a[1])
test_cases = test_cases -1
result = func(N, M)
print("%.2f" % round(result, 2))
if __name__ == '__main__':
sys.setrecursionlimit(1500)
sys.exit(main(*sys.argv))
It gives the same answer for N = 1000 ,M = 1 and N = 1000 , M = 2
On searching I found that limit of float expires over 10^400. My question is how to overcome it
Floats in Python are IEEE doubles: they are not unlimited precision. But if your computation only needs integers, then just use integers: they are unlimited precision. Unfortunately, I think your computation does not stay within the integers.
There are third-party packages built on GMP that provide arbitrary-precision floats: https://www.google.com/search?q=python%20gmp
I maintain one of the Python to GMP/MPFR libraries and I tested your function. After checking the results and looking at your function, I think your function remains entirely in the integers. The following function returns the same values:
def func(N, M):
if M == 0:
return 2**(N+1) - 2
elif N == M:
return 0
else:
return func(N, M+1)//2 + 2**N
The limiting factor with Python's builtin float is not the exponent range (roughly 10**308) but the precision (53 bits). You need around N bits of precision to distinguish between func(N,1) and func(N,2)
Consider using an arbitrary precision floating-point library, for example the bigfloat package, or mpmath.

Categories