(I'm a total beginner)
I want to write a recursive function which can tell me if a number is a prime number or not: but I keep getting the same recursion error :
here is my code :
from math import *
def has_a_divider(n,p):
if n%p==0:
return True
elif has_a_divider(n,(p-1))!= True:
return False
else:
return False
def is_prime(a):
if has_a_divider(a,sqrt(a))==False:
return True
else:
return False
Your problem is sqrt(a) which returns a float instead of the int your code requires.
You can replace it by ceil(sqrt(a)) to get an int from it.
Also, this code does not work for finding if the number is prime as all numbers will have at least 1 has a divider. A possible solution is to update has_a_divider to check for dividers bigger than 1.
A possible implementation:
from math import ceil, sqrt
def has_a_divider(n,p):
if p < 2:
return False
if n % p==0:
return True
return has_a_divider(n,(p-1))
def is_prime(a):
if a == 1:
return False
return not has_a_divider(a,ceil(sqrt(a)))
print(is_prime(3))
print(is_prime(5))
print(is_prime(4))
Related
Can someone please explain to me why this code works for 2 as well:
def is_prime_v1(n):
'''Return True if 'n' is prime. False otherwise.'''
if n == 1:
return False
for d in range(2,n):
if n % d == 0:
return False
return True
when the code gets to
for d in range(2,n):
if n % d == 0:
return False
return True
Would it not see this as start at 2 but go up to and do not include 2?
This does not make complete sense to me.
The formula works but if you try and create a list on that range like so:
x = list(range(2,2))
You get an empty list.
Please could anyone explain this to me? Does it work for two as well because it would not be able to do the below on range(2,2) and then moves down to return True?
if n % d == 0:
return False
return True
Thanks
because for loop is never executed , list(range(2,2)) == [], so the program didn't iterate over range and directly proced to return True statement
Your assumption is correct. The upper value of the range function is not put through the for loop. To overcome this, you could just add or n == 2 to the third line of your program.
def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,4000000):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
What is wrong with this code? It does not return anything but it looks good according to me.
you should return sum(L) from function not from for loop follow below code
def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,20):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
and other thing look at the range its too much,because of this it will take some time or may produce any memory related error, so reduce it for testing.
The return statement is set to the wrong increment. It is executed the first time i % 2 == 0 becomes true (which is i == 2 in your case).
def fib(n):
if n<= 1:
return n
else:
return(fib(n-1)+fib(n-2))
def comp():
L=[]
for i in range(1,4000000):
if i % 2 ==0:
L.append(fib(i))
return sum(L)
print(comp())
The above code is not going to work, though. Are you aware of how big this number would get?
Try
for i in range(1,40):
as a start. It took quite a few seconds on my machine. Result is 63245985.
The webpage to test the code is here:
https://leetcode.com/problems/sqrtx/description/
I handed in these code and passed:
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x==1:
return 1
lowest=0.0
uppest=x*1.0
count=1
middle=(lowest+uppest)*0.5
while (abs(middle*middle-x)>0.001) and (count<=10000):
if middle*middle>x:
uppest=middle
else:
lowest=middle
middle=(lowest+uppest)*0.5
count=count+1
return int(middle)
but when I change
while (abs(middle*middle-x)>0.001) and (count<=10000):
into
while (abs(middle*middle-x)>0.0001) and (count<=10000):
or add more '0' like 0.00000000001 and use '9' as an input to test, it gets wrong
The output should be 3, but I got 2
How can I solve this kind of problem while using the Bisection Method?
I don't want to use the library (I know that using library is the easiest way but I want to learn more)
It is more like a math problem rather than python, just insert
print(middle,middle**2>x)
for debugging purposes.
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x==1:
return 1
lowest=0.0
uppest=x*1.0
count=1
middle=(lowest+uppest)*0.5
while (abs(middle*middle-x)>0.0001) and (count<=10000):
if middle*middle>x:
uppest=middle
else:
lowest=middle
middle=(lowest+uppest)*0.5
count=count+1
print(middle,middle**2>x)
return int(middle)
sol=Solution()
print(sol.mySqrt(9))
The output
2.25 False
3.375 True
2.8125 False
3.09375 True
2.953125 False
3.0234375 True
2.98828125 False
3.005859375 True
2.9970703125 False
3.00146484375 True
2.999267578125 False
3.0003662109375 True
2.99981689453125 False
3.000091552734375 True
2.9999542236328125 False
3.0000228881835938 True
2.999988555908203 False
2
You can see the reason already.
Also I wonder why cannot you just use
round(middle)
The culprit is
return int(middle)
The reason you obtain 2 is because your are casting a number such as 2.99998855591 into int, which is the equivalent of floor(x)
After a number of iteration n0, the error sqrt(x) - middle between the target value and the value of middle follow a damped oscillation.
Just round to the closest integer instead
return round(middle)
See other answers for what is happening. The solution is:
return int(middle + 0.5)
which is rounding towards the nearest integer.
A bigger problem is of course that you're converting intermediate values to float when calculating an integer square root. Floats have a very limited range compared to Python ints. Try something like this instead:
def int_sqrt(n):
"""Return integer square root of integer ``n``.
"""
x = n
y = (x + 1) >> 1
while y < x:
x = y
y = (x + n // x) >> 1
return x
and e.g. run it on int_sqrt(2**12345-1) which should return a 1858 digit number.
I'm trying to find the largest prime factor of a given number (600851475143) using Python. I've made the following code, but I don't know what is wrong and whether I am using right code Please help find my mistake and improve it.
import math
def t(x):
l=[]
for i in range(1,int(math.sqrt(x))):
if x%i==0:
l.append(i)
return l
def check(y):
for i in range(2,1+y/2):
if y%i==0:
return 'this is not prime'
return 'ya'
print t(600851475143)
print check(486847)
You need to check that everything you're adding to the list is actually a prime
for i in range(1,int(math.sqrt(x))):
if (x % i) != 0:
continue
if check(i):
l.append(i)
Then, pop the last (largest) element of the list:
return l.pop()
You can also check up to the square root:
def check(y):
for i in range(2,int(math.sqrt(y))):
if (y % i) == 0:
return False
return True
Here's a slightly modified version that iterates backwards (as suggested by pzp), and returns as soon as a prime is found:
#!/usr/bin/env python
import math
def t(x):
for i in xrange(int(math.sqrt(x)), 1, -1):
if (x % i) != 0:
continue
if check(i):
return i
return None
def check(y):
for i in range(2, int(math.sqrt(y))):
if (y % i) == 0:
return False
return True
print t(600851475143)
print check(6857)
You're pretty close. Your check() is returning before you want it to. You want:
def check(y):
for i in range(2,1+y/2):
if y%i==0:
return 'this is not prime'
return 'ya'
This will wait until you've check all the numbers < y before returning false. Right now, it checks 2, then returns either true or false.
Also t() is returning all factors, rather than the greatest factor. For just the greatest factor (assuming there is one), you want return l[-1]
EDIT:
Ok, I think I get what you're going for. By using this t() and check(), you can get the largest prime by with:
def t(x):
l=[]
for i in range(1,int(math.sqrt(x))):
if x%i==0:
l.append(i)
return l
#Notice, return list of all factors
def check(y):
for i in range(2,1+y/2):
if y%i==0:
return False
return True
number_to_check = 92873465
prime_factors = []
for factor in t(number_to_check): # Iterate through factors returned from t()
if check(factor):
prime_factors.append(factor)
print "Largest Prime Factor: " + prime_factors[-1]
I am working on this question from school, and I wrote the function I thought was the right one (we need to use recursion with no loops)
def subset_sum(numbers, target):
'''
numbers - a list of positive integers
target - a non-negative integer
returns True if the list 'numbers' has a sub-list with sum 'target',
False otherwise.
'''
# Your code for question #4 starts here
if sum(numbers[1:]) == target or target == 0:
return True
if sum(numbers[1:]) == (target - numbers[0]):
return True
if len(numbers) == 1 and numbers[0] == target:
return True
if len(numbers) == 1 and numbers[0] != target:
return False
else:
subset_sum(numbers[1:], target)
For some inputs get the right output like subset_sum([4,4,4], 12) or subset_sum([4,4,4], 8) but for subset_sum([4,4,4], 4) I get no output.
Can someone take a look and tell me what's wrong here?
When it doesn't give any output there are no errors, just blank.
You have to return the result of subset_sum in the else branch:
else:
return subset_sum(numbers[1:], target)