I am trying to make power function by recursion.
But I got run time error like Maximum recursion depth exceeded.
I will appreciate any help!!
Here is my code.
def fast_power(a,n):
if(n==0):
return 1
else:
if(n%2==0):
return fast_power(fast_power(a,n/2),2)
else:
return fast_power(fast_power(a,n/2),2)*a
You should use n // 2 instead of n / 2:
>>> 5 // 2
2
>>> 5 / 2
2.5
(At least in python3)
The problem is that once you end up with floats it takes quite a while before you end up at 0 by dividing by 2:
>>> from itertools import count
>>> n = 5
>>> for i in count():
... n /= 2
... if n == 0:
... break
...
>>> i
1076
So as you can see you would need more than 1000 recursive calls to reach 0 from 5, and that's above the default recursion limit. Besides: that algorithm is meant to be run with integer numbers.
This said I'd write that function as something like:
def fast_power(a, n):
if n == 0:
return 1
tmp = fast_power(a, n//2)
tmp *= tmp
return a*tmp if n%2 else tmp
Which produces:
>>> fast_power(2, 7)
128
>>> fast_power(3, 7)
2187
>>> fast_power(13, 793)
22755080661651301134628922146701289018723006552429644877562239367125245900453849234455323305726135714456994505688015462580473825073733493280791059868764599730367896428134533515091867511617127882942739592792838327544860344501784014930389049910558877662640122357152582905314163703803827192606896583114428235695115603966134132126414026659477774724471137498587452807465366378927445362356200526278861707511302663034996964296170951925219431414726359869227380059895627848341129113432175217372073248096983111394024987891966713095153672274972773169033889294808595643958156933979639791684384157282173718024930353085371267915606772545626201802945545406048262062221518066352534122215300640672237064641040065334712571485001684857748001990405649808379706945473443683240715198330842716984731885709953720968428395490414067791229792734370523603401019458798402338043728152982948501103056283713360751853
I believe #Bakuriu's explanation of the problem is incomplete. Not his reimplementation, but his explanation of your bug(s). You might convince yourself of this by replacing / with // in your original code and try:
fast_power(2, 2)
it still exceeds the stack. Try expanding the stack ten fold:
sys.setrecursionlimit(10000)
it still exceeds the stack. The reason is you also have an infinte loop:
if (n % 2 == 0):
return fast_power(..., 2)
Since 2 % 2 == 0, this simply keeps recursing forever. Adding another base case:
if n == 2:
return a * a
fixes the problem. A complete solution:
def fast_power(a, n):
if n == 0:
return 1
# if n == 1:
# return a
if n == 2:
return a * a
if n % 2 == 0:
return fast_power(fast_power(a, n // 2), 2)
return a * fast_power(fast_power(a, n // 2), 2)
Related
I just started working with recursive functions and I have to create a function that receives an integer and returns a new number that contains only the even digits. For example if it receives 23456, it should return 246. This is what I've tried:
def newInt(n):
dig = n % 10
if dig % 2 == 1:
return newInt(n//10)
elif dig % 2 == 0:
return str(n) + newInt(n//10)
print(newInt(32))
But I'm getting the following error:
RecursionError: maximum recursion depth exceeded in __instancecheck__
Any hints on what should I do to fix it?
You need a base case. There's also no need to convert any of the integers to strings. Here is a working version of newInt() that resolves both of these issues:
def newInt(n):
if not n:
return 0
dig = n % 10
if dig % 2 == 1:
return newInt(n // 10)
else:
return 10 * newInt(n // 10) + dig
Your issue is that you have no condition to stop recursion - every call to newInt results in another call. One way to stop would be to check if n is less than 10 and then just return n if it is even. For example:
def newInt(n):
if n < 10:
return n if n % 2 == 0 else 0
dig = n % 10
if dig % 2 == 1:
return newInt(n//10)
elif dig % 2 == 0:
return newInt(n//10) * 10 + dig
Note I have modified your function to return an integer rather than a string.
Here is a variant with divmod. Uncomment the print to see how it works:
def newInt(n):
d,r = divmod(n,10)
# print(n,d,r)
if d == 0:
return 0 if r%2 else r
if r % 2:
return newInt(d)
else:
return 10*newInt(d)+r
print(newInt(212033450))
Output: 22040
You don't even need to break out dig for each loop:
def newInt(n):
if n:
if n & 1:
return newInt(n // 10)
else:
return 10 * newInt(n // 10) + (n % 10)
return 0
This is a rewrite of #mozway's algortihm using Python 3.10 match..case syntax -
def newInt(n):
match divmod(n, 10):
case (0, r) if r & 1:
return 0
case (0, r):
return r
case (d, r) if r & 1:
return newInt(d)
case (d, r):
return 10 * newInt(d) + r
print(newInt(67120593306737201))
6200620
Note r & 1 is more efficient for testing if a number is even or odd. r % 2 performs division whereas & simply checks the first bit.
I want to get a prime number set within 2^63 - 1 in Python,I have seen the following code on the web:
limit = 2**63 - 2
p = [True] * (limit + 1)
# p = bitarray(limit + 1)
p[0] = p[1] = False
for i in range(2, int(math.sqrt(limit) + 1)):
if p[i]:
for j in range(i * i, limit + 1, i):
p[j] = False
prime = [i for i in range(limit + 1) if p[i]]
print(prime)
But when I run this program, the compiler complains that can not fit 'int' into an index-sized integer.
I tried to solve the problem with bitarray, but the index of the array is still too big.
You can use the following code. It is using the Sieve of Eratosthenes in combination with a generator function in order to reduce the memory usage of this algorithm. It is furthermore exploiting the less commonly known fact that every prim number > 4 can be written as 6*n ± 1.
import math
limit = 2 ** 63 - 1
def isPrim(n, belowPrims):
limit = int(math.sqrt(n))
for prim in belowPrims:
if prim > limit: break
if n % prim == 0: return False
return True
def calcPrims():
yield 2
yield 3
toTest, nextN = [], 6
while True:
p1 = nextN - 1
if isPrim(p1, toTest):
yield p1
toTest.append(p1)
p2 = nextN + 1
if isPrim(p2, toTest):
yield p2
toTest.append(p2)
nextN += 6
for prim in calcPrims():
if prim > limit:
break
print(prim)
Edit
This link here https://primes.utm.edu/notes/faq/six.html explains briefly why every prim number can be written in the form 6*n ± 1.
You can use sympy:
import sympy
print(list(sympy.primerange(0,2**63-1)))
but as 2^63 is quite large this will take some time.
if you have a primes() generator of some kind, you could do this:
is_prime_var = 0
MAX = 1 << 5
last_p = 0
for p in primes():
if p > MAX:
break
print(p, p-last_p)
is_prime_var <<= (p - last_p)
is_prime_var |= 1
last_p = p
is_prime_var <<= (MAX - last_p - 1)
now the locations of the primes are stored (in reversed order) in the integer is_prime_var.
then the expression (is_prime >> (MAX-n-1)) & 1 would be 1 if n is prime; 0 otherwise:
def is_prime(n):
return bool((is_prime_var >> (MAX-n-1)) & 1)
you could use primes() from this excellent answer as prime generator.
thers is also this answer of mine about a fast and memory-efficient sieve of eratosthenes. might also be interesting.
I've written this function to calculate sin(x) using Taylor series to any specified degree of accuracy, 'N terms', my problem is the results aren't being returned as expected and I can't figure out why, any help would be appreciated.
What is am expecting is:
1 6.28318530718
2 -35.0585169332
3 46.5467323429
4 -30.1591274102
5 11.8995665347
6 -3.19507604213
7 0.624876542716
8 -0.0932457590621
9 0.0109834031461
What I am getting is:
1 None
2 6.28318530718
3 -35.0585169332
4 46.5467323429
5 -30.1591274102
6 11.8995665347
7 -3.19507604213
8 0.624876542716
9 -0.0932457590621
Thanks in advance.
def factorial(x):
if x <= 1:
return 1
else:
return x * factorial(x-1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
else:
sign = 1
result = result + (((x ** power)*sign) / factorial(power))
return result
pi = 3.141592653589793
for i in range(1,10):
print i, sinNterms(2*pi, i)
I see that you are putting the return under the for which will break it out of the while loop. You should explain if this is what you mean to do. However, given the for i in range(1,10): means that you will ignore the first entry and return None when the input argument i is 1. Is this really what you wanted? Also, since you always exit after the calculation, you should not do a while N > 1 but use if N > 1 to avoid infinite recursion.
The reason why your results are off is because you are using range incorrectly. range(2, N) gives you a list of numbers from 2 to N-1. Thus range(2, 2) gives you an empty list.
You should calculate the range(2, N+1)
def sinNterms(x, N):
x = float(x)
while N >1:
result = x
for i in range(2, N):
Your comment explains that you have the lines of code in the wrong order. You should have
def sinNterms(x, N):
x = float(x)
result = x
# replace the while with an if since you do not need a loop
# Otherwise you would get an infinite recursion
if N > 1:
for i in range(2, N+1):
power = ((2 * i)-1)
sign = 1
if i % 2 == 0:
sign = -1
# The else is not needed as this is the default
# else:
# sign = 1
# use += operator for the calculation
result += (((x ** power)*sign) / factorial(power))
# Now return the value with the indentation under the if N > 1
return result
Note that in order to handle things set factorial to return a float not an int.
An alternative method that saves some calculations is
def sinNterms(x, N):
x = float(x)
lim = 1e-12
result = 0
sign = 1
# This range gives the odd numbers, saves calculation.
for i in range(1, 2*(N+1), 2):
# use += operator for the calculation
temp = ((x ** i)*sign) / factorial(i)
if fabs(temp) < lim:
break
result += temp
sign *= -1
return result
I solved Euler problem 14 but the program I used is very slow. I had a look at what the others did and they all came up with elegant solutions. I tried to understand their code without much success.
Here is my code (the function to determine the length of the Collatz chain
def collatz(n):
a=1
while n!=1:
if n%2==0:
n=n/2
else:
n=3*n+1
a+=1
return a
Then I used brute force. It is slow and I know it is weak. Could someone tell me why my code is weak and how I can improve my code in plain English.
Bear in mind that I am a beginner, my programming skills are basic.
Rather than computing every possible chain from the start to the end, you can keep a cache of chain starts and their resulting length. For example, for the chain
13 40 20 10 5 16 8 4 2 1
you could remember the following:
The Collatz chain that starts with 13 has length 10
The Collatz chain that starts with 40 has length 9
The Collatz chain starting with 20 has length 8
... and so on.
We can then use this saved information to stop computing a chain as soon as we encounter a number which is already in our cache.
Implementation
Use dictionaries in Python to associate starting numbers with their chain length:
chain_sizes = {}
chain_sizes[13] = 10
chain_sizes[40] = 9
chain_sizes[40] # => 9
20 in chain_sizes # => False
Now you just have to adapt your algorithm to make use of this dictionary (filling it with values as well as looking up intermediate numbers).
By the way, this can be expressed very nicely using recursion. The chain sizes that can occur here will not overflow the stack :)
Briefly, because my English is horrible ;-)
Forall n >= 1, C(n) = n/2 if n even,
3*n + 1 if n odd
It is possible to calculate several consecutive iterates at once.
kth iterate of a number ending in k 0 bits:
C^k(a*2^k) = a
(2k)th iterate of a number ending in k 1 bits:
C^(2k)(a*2^k + 2^k - 1) = a*3^k + 3^k - 1 = (a + 1)*3^k - 1
Cf. formula on Wikipédia article (in French); see also my website (in French), and Module tnp1 in my Python package DSPython.
Combine the following code with the technique of memoization explained by Niklas B :
#!/usr/bin/env python
# -*- coding: latin-1 -*-
from __future__ import division # Python 3 style in Python 2
from __future__ import print_function # Python 3 style in Python 2
def C(n):
"""Pre: n: int >= 1
Result: int >= 1"""
return (n//2 if n%2 == 0
else n*3 + 1)
def Ck(n, k):
"""Pre: n: int >= 1
k: int >= 0
Result: int >= 1"""
while k > 0:
while (n%2 == 0) and k: # n even
n //= 2
k -= 1
if (n == 1) and k:
n = 4
k -= 1
else:
nb = 0
while (n > 1) and n%2 and (k > 1): # n odd != 1
n //= 2
nb += 1
k -= 2
if n%2 and (k == 1):
n = (n + 1)*(3**(nb + 1)) - 2
k -= 1
elif nb:
n = (n + 1)*(3**nb) - 1
return n
def C_length(n):
"""Pre: n: int >= 1
Result: int >= 1"""
l = 1
while n > 1:
while (n > 1) and (n%2 == 0): # n even
n //= 2
l += 1
nb = 0
while (n > 1) and n%2: # n odd != 1
n //= 2
nb += 1
l += 2
if nb:
n = (n + 1)*(3**nb) - 1
return l
if __name__ == '__main__':
for n in range(1, 51):
print(n, ': length =', C_length(n))
I implemented the Miller-Rabin prime test algorithm found on wikipedia with Python 3.
It seems to be working correctly with most numbers but occasionaly fail on certain numbers.
For example, the prime number 99999999999999997 is judged to be NOT prime.
I implemented the algorithm line by line and I have no clue where the problem is.
Can any one help me ?
Here is my code.
the test input is:
1
99999999999999997
(No empty line between two lines.)
And the expected output should be YES, but it gives NO on my machine.
import random
def isPrime(n, k = 5):
'''
Primality test using Miller-Rabin method.
n The number to test primality.
k The number of M-R test to perform.
'''
if n == 1:
return False
if n == 2 or n == 3:
return True
if n % 2 == 0:
return False
# Calculate d
nn = n - 1
s = 1
while nn % (2 ** s) == 0:
s += 1
s -= 1
d = int(nn / (2 ** s))
for i in range(k):
a = random.randint(2, n - 1)
x = pow(a,d,n)
if x == 1 or x == n - 1:
continue
flag = True
for r in range(1, s):
x = pow(x,2,n)
if x == 1:
return False
if x == n - 1:
flag = False
break
if not flag:
continue
return False
return True
count = int(input())
for i in range(count):
if isPrime(int(input())):
print('YES')
else:
print('NO')
This is an implementation of Miller-Rabin I wrote a while ago. It has never given me an unexpected result -- though that doesn't mean it won't! It is substantially identical to the one you pasted, and it declares 99999999999999997 to be prime. Yours did too, when I tested it -- so that's a second to Mikola's opinion. But see below for one possible problem that I can't easily test... scratch that, I tested it, and it was the problem.
When it comes to primality testing, I'm no expert, but I spent a lot of time thinking about and coming to understand Miller-Rabin, and I'm pretty sure your implementation is spot-on.
def is_prime_candidate(self, p, iterations=7):
if p == 1 or p % 2 == 0: return False
elif p < 1: raise ValueError("is_prime_candidate: n must be a positive integer")
elif p < self.maxsmallprime: return p in self.smallprimes
odd = p - 1
count = 0
while odd % 2 == 0:
odd //= 2
count += 1
for i in range(iterations):
r = random.randrange(2, p - 2)
test = pow(r, odd, p)
if test == 1 or test == p - 1: continue
for j in range(count - 1):
test = pow(test, 2, p)
if test == 1: return False
if test == p - 1: break
else: return False
print i
return True
The one thing I noticed about your code that seemed off was this:
d = int(nn / (2 ** s))
Why int, I thought to myself. Then I realized you must be using Python 3. So that means you're doing floating point arithmetic here and then converting to int. That seemed iffy. So I tested it on ideone. And lo! the result was False. So I changed the code to use explicit floor division (d = nn // (2 ** s)). And lo! it was True.
I am going to reiterate my comment, since my testing seems to indicate your example is working. I strongly suspect that you just mistyped your test case. Maybe you can try taking a second look at it? Here is what I got from running it:
In [12]: millerrabin.isPrime(99999999999999997, 5)
Out[12]: True
EDIT: I just ran the updated version, and here is the output from the console:
1
99999999999999997
YES
Again, this looks correct.
From what I can see, the Miller-Rabin algorithm is only probabilistic. Were you not aware of this, or are you using a modified, non probabilistic version?