I am pretty sure that this must be some glaringly stupid mistake by me. But can anyone explain what is wrong in this division code using recursion. I know there are a lot of alternatives, but I need to know what is wrong with this
def division(a, b):
x = 0
if a < b:
return x
else:
x += 1
return division(a - b, b)
return x
When I do division(10, 2), it gives me 0 as output
You always set your local variable x to 0.
Then if the dividend is smaller than the divisor you return that x which is of course 0.
On the other hand when the dividend is greater or equal to the divisor you increment x by 1 and do a recursive call with a decremented dividend which will of course lead to the first case at the end and still you return an x which holds the value of 0.
Note: Nonetheless your final return is not reachable since both your if and else branch contains a return.
So please try considering this solution:
def division(a, b):
if a < b:
return 0
else:
return 1 + division(a-b, b)
Update:
A possible solution for working with negative integers following python's round towards negative infinity division:
def division_with_negatives(a, b):
a_abs, b_abs = abs(a), abs(b)
if (a >= 0 and b >= 0) or (a < 0 and b < 0):
# branch for positive results
if a_abs < b_abs:
return 0
else:
return 1 + division_with_negatives(a_abs - b_abs, b_abs)
else:
# branch for negative results
if b_abs > a_abs or a_abs == b_abs:
return -1
else:
return -1 + division_with_negatives(a_abs - b_abs, -b_abs)
assert division_with_negatives(-4, 1) == -4 // 1
assert division_with_negatives(10, 2) == 10 // 2
assert division_with_negatives(1, -5) == 1 // -5
assert division_with_negatives(-3, -2) == -3 // -2
This might save you from RecursionError:
def div(x, y):
if y == 0:
return 0
elif x == y:
return 1
elif x < y:
if y * -1 == x:
return -1
elif x % y == 0:
return 1 + div(x - y, y)
else:
return 0
else:
if y < 0:
return 1 - div(x - y, -y)
else:
return 1 + div(x - y, y)
#Application
A = div(1, 2)
B = div(-9, 9)
C = div(3, 2)
D = div(-9, -3)
E = div(100, -2)
print(A) # 0
print(B) # -1
print(C) # 1
print(D) # 3
print(E) # -50
Your escape condition is if a < b. That means that for this function to terminate, this must be fulfilled to leave the recursion. However, because x is declared at the top of the function, only redefined inside the body of the else statement but never returned, the function will always terminate with a value of x = 0.
You should either set x = 1 + division(a-b,b) or return division(a-b,b) + 1 and remove the unreachable returnat the end.
def div(a, b, x):
if a < b:
return x
else:
x +=1
return div(a - b, b, x)
print(div(130, 10, 0))
# 13
This might work a little better for you:
def division(a,b,x=0):
if a < b:
return x
else:
x += 1
return division(a-b,b,x)
return x
Every time your function ran through a new recusion, you were setting x to 0. This way, it defaults to 0 if x is not specified, and should work like I think you want.
Also note that this will not work for negative numbers, but you probably knew that :)
With global you get:
def division(a,b):
global x
if a < b: return x
else:
x += 1
return division(a-b,b)
x=0
print (division(10,2))
But you have to set x to zero every time before call the division
i think this is best way, this way u can get floating answer also
def division(a,b):
if a == 0 or a == 1 or a == 2:
return b
else:
return a / division(a % b,b)
print(division(9,2))
Related
I need to generate the result of the log.
I know that:
Then I made my code:
def log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
print(log_b)
return int(round(log_b))
But it works very slowly. Can I use other method?
One other thing you might want to consider is using the Taylor series of the natural logarithm:
Once you've approximated the natural log using a number of terms from this series, it is easy to change base:
EDIT: Here's another useful identity:
Using this, we could write something along the lines of
def ln(x):
n = 1000.0
return n * ((x ** (1/n)) - 1)
Testing it out, we have:
print ln(math.e), math.log(math.e)
print ln(0.5), math.log(0.5)
print ln(100.0), math.log(100.0)
Output:
1.00050016671 1.0
-0.692907009547 -0.69314718056
4.6157902784 4.60517018599
This shows our value compared to the math.log value (separated by a space) and, as you can see, we're pretty accurate. You'll probably start to lose some accuracy as you get very large (e.g. ln(10000) will be about 0.4 greater than it should), but you can always increase n if you need to.
I used recursion:
def myLog(x, b):
if x < b:
return 0
return 1 + myLog(x/b, b)
You can use binary search for that.
You can get more information on binary search on Wikipedia:
Binary search;
Doubling search.
# search for log_base(x) in range [mn, mx] using binary search
def log_in_range(x, base, mn, mx):
if (mn <= mx):
med = (mn + mx) / 2.0
y = base ** med
if abs(y - x) < 0.00001: # or if math.isclose(x, y): https://docs.python.org/3/library/math.html#math.isclose
return med
elif x > y:
return log_in_range(x, base, med, mx)
elif x < y:
return log_in_range(x, base, mn, med)
return 0
# determine range using doubling search, then call log_in_range
def log(x, base):
if base <= 0 or base == 1 or x <= 0:
raise ValueError('math domain error')
elif 0 < base < 1:
return -log(x, 1/base)
elif 1 <= x and 1 < base:
mx = 1
y = base
while y < x:
y *= y
mx *= 2
return log_in_range(x, base, 0, mx)
elif 0 <= x < 1 and 1 < base:
mn = -1
y = 1/base
while y > x:
y = y ** 0.5
mn *= 2
return log_in_range(x, base, mn, 0)
import math
try :
number_and_base = input() ##input the values for number and base
##assigning those values for the variables
number = int(number_and_base.split()[0])
base = int(number_and_base.split()[1])
##exception handling
except ValueError :
print ("Invalid input...!")
##program
else:
n1 = 1 ##taking an initial value to iterate
while(number >= int(round(base**(n1),0))) : ##finding the most similer value to the number given, varying the vlaue of the power
n1 += 0.000001 ##increasing the initial value bit by bit
n2 = n1-0.0001
if abs(number-base**(n2)) < abs(base**(n1)-number) :
n = n2
else :
n = n1
print(math.floor(n)) ##output value
Comparison:-
This is how your log works:-
def your_log(x, base):
log_b = 2
while x != int(round(base ** log_b)):
log_b += 0.01
#print log_b
return int(round(log_b))
print your_log(16, 2)
# %timeit %run your_log.py
# 1000 loops, best of 3: 579 us per loop
This is my proposed improvement:-
def my_log(x, base):
count = -1
while x > 0:
x /= base
count += 1
if x == 0:
return count
print my_log(16, 2)
# %timeit %run my_log.py
# 1000 loops, best of 3: 321 us per loop
which is faster, using the %timeit magic function in iPython to time the execution for comparison.
It will be long process since it goes in a loop. Therefore,
def log(x,base):
result = ln(x)/ln(base)
return result
def ln(x):
val = x
return 99999999*(x**(1/99999999)-1)
log(8,3)
Values are nearly equal but not exact.
So, I was writing overly complex answers for simple problems on Codewars as I often do, and one of the problems was,
Multiply two numbers
It wanted me to put:
return a * b
But I wanted to make a function that multiplied two numbers by itself, without the help of the '*' operator or any other thing that multiplied values together.
Pretty easy, I thought. I just add the a value to some empty value b amount of times.
It worked pretty well, up until one of the tests included decimals. I then wrote this to get the average of.. well something. That clearly didn't work:
def multiply(a, b):
leftside = 0
rightside = 0
average = 0
for i in range(int(b)):
leftside += a
for i in range(int(a)):
rightside += b
average = (leftside+rightside) / 2
return average
So basically, what I'm asking is if there's a way to naturally, without any other functions or operators(besides addition and essential things) to multiply values.
If you allow division by 2 like your own attempt does, then I guess this might be decent:
def multiply(a, b):
while b >= 1:
b /= 2
a += a
result = 0
while b:
b += b
a /= 2
if b >= 1:
result += a
b -= 1
return result
Or implementing halving myself, without using division:
def half(x):
result = 0
while x:
y = 0
Y = 2.2250738585072014e-308
while Y + Y <= x:
y = Y
Y += Y
x -= Y
result += y
return result
def multiply(a, b):
while b >= 1:
b = half(b)
a += a
result = 0
while b:
b += b
a = half(a)
if b >= 1:
result += a
b -= 1
return result
I need a function that takes n and returns 2n - 1 . It sounds simple enough, but the function has to be recursive. So far I have just 2n:
def required_steps(n):
if n == 0:
return 1
return 2 * req_steps(n-1)
The exercise states: "You can assume that the parameter n is always a positive integer and greater than 0"
2**n -1 is also 1+2+4+...+2n-1 which can made into a single recursive function (without the second one to subtract 1 from the power of 2).
Hint: 1+2*(1+2*(...))
Solution below, don't look if you want to try the hint first.
This works if n is guaranteed to be greater than zero (as was actually promised in the problem statement):
def required_steps(n):
if n == 1: # changed because we need one less going down
return 1
return 1 + 2 * required_steps(n-1)
A more robust version would handle zero and negative values too:
def required_steps(n):
if n < 0:
raise ValueError("n must be non-negative")
if n == 0:
return 0
return 1 + 2 * required_steps(n-1)
(Adding a check for non-integers is left as an exercise.)
To solve a problem with a recursive approach you would have to find out how you can define the function with a given input in terms of the same function with a different input. In this case, since f(n) = 2 * f(n - 1) + 1, you can do:
def required_steps(n):
return n and 2 * required_steps(n - 1) + 1
so that:
for i in range(5):
print(required_steps(i))
outputs:
0
1
3
7
15
You can extract the really recursive part to another function
def f(n):
return required_steps(n) - 1
Or you can set a flag and define just when to subtract
def required_steps(n, sub=True):
if n == 0: return 1
return 2 * required_steps(n-1, False) - sub
>>> print(required_steps(10))
1023
Using an additional parameter for the result, r -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r * 2)
for x in range(6):
print(f"f({x}) = {required_steps(x)}")
# f(0) = 0
# f(1) = 1
# f(2) = 3
# f(3) = 7
# f(4) = 15
# f(5) = 31
You can also write it using bitwise left shift, << -
def required_steps (n = 0, r = 1):
if n == 0:
return r - 1
else:
return required_steps(n - 1, r << 1)
The output is the same
Have a placeholder to remember original value of n and then for the very first step i.e. n == N, return 2^n-1
n = 10
# constant to hold initial value of n
N = n
def required_steps(n, N):
if n == 0:
return 1
elif n == N:
return 2 * required_steps(n-1, N) - 1
return 2 * required_steps(n-1, N)
required_steps(n, N)
One way to get the offset of "-1" is to apply it in the return from the first function call using an argument with a default value, then explicitly set the offset argument to zero during the recursive calls.
def required_steps(n, offset = -1):
if n == 0:
return 1
return offset + 2 * required_steps(n-1,0)
On top of all the awesome answers given earlier, below will show its implementation with inner functions.
def outer(n):
k=n
def p(n):
if n==1:
return 2
if n==k:
return 2*p(n-1)-1
return 2*p(n-1)
return p(n)
n=5
print(outer(n))
Basically, it is assigning a global value of n to k and recursing through it with appropriate comparisons.
(Python 3.x)
z=[]
x=0
while 1==1:
x=x+1
y=1
z.append(x)
while y==1:
a = 0
b = 0
if z(a)==x:
print(x)
y = 2
elif x%z(a)!= 0:
a = a+1
elif b == 2:
y = 2
else:
b = b+1
So, I made a code to find all the prime numbers until python crashes. However, it relies on z(a) for it to work. The idea is that as "a" changes, it moves on in the list.
"z(a)" is where the error lies, so does anyone know a way to fix this?
z is a list. You can approach values inside it by indexes using the z[a] operator (and not z(a) which assumes a function call with a as parameter).
I've taken the liberty of using boolean variables, += operators and unpacking values:
z = []
x = 0
while True:
x += 1
y = True
z.append(x)
while y:
a, b = 0, 0
if z[a] == x:
print(x)
y = False
elif x % z[a]: a += 1
elif b == 2: y = False
else: b += 1
I believe that's what you want to achieve (infinitely incrementing prime generator):
def prime (n): return not any([n % i == 0 for i in range(2, n)])
x = 0
while True:
if prime(x): print(x)
x += 1
I was wondering if I could calculate the logarithm of a number based on a number relative to a base (for example, log base 2 of 16) without actually using log(). I managed to do it, but I don't believe it is very efficient.
This is my code in Python:
def myLog(x,b):
exp=0
ans=b**exp
while x!=ans:
ans=b**exp
if ans==x:
return exp
exp=exp+1
So I could give it myLog(16,2) and it should return 4. And indeed it does, however I believe it is not the most efficient way, so how could I fix it and make my code more efficient, not just in this case, but in most of them?
Try recursion:
def func(a, b, ans=0):
if a/b == 1:
return ans + 1
else: return func(a/b, b, ans+1)
In [26]: func(16, 2)
Out[26]: 4
In [27]: func(8, 2)
Out[27]: 3
In [28]: func(16,4)
Out[28]: 2
Here's my two cents worth:
def myLog(x,b):
exp = 0
ans = 1
while ans<x:
ans *= b
exp += 1
if ans == x:
return exp
else:
raise ValueError("can't find a suitable exponent")
In [10]: myLog(16,2)
Out[10]: 4
Hope this helps
You're not taking into account if someone gives a negative value such as myLog(-1,2) or if it is 1 myLog(1,2), then you compute ans before the loop which you know it always be 0 because you put exp = 0, then in the loop you compute it again without before changing the exp.
logarithm python
Assumes:
x: a positive integer
b: a positive integer; b >= 2
returns: log_b(x), or, the logarithm of x relative to a base b.
Seems the shortest way is:
def myLog(x, b):
ans = 0
while b <= x:
ans += 1
x /= b
return ans
Or recursively:
def myLog(x, b):
if (b > x): return 0
else: return 1 + myLog(x/b, b)
Because it is an endless loop:
def myLog(x,b):
exp = 0
ans = b**exp
while x != ans:
ans = b**exp
if ans>x:
return -1
if ans == x:
return exp
exp = exp+1
See also:
What algorithm is used by computers to calculate logarithms?
Taylor series
This version adds support for non-integer outputs:
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
Does not work for all numbers. log(5,10) returns 0.00000 when it should be 0.69897