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
Related
Having the hardest time figuring out rounding issue in my python code that is supposed to output the multiplied value of 2 numbers using Karatsuba's algorithm [1, 2].
This is my code:
def mult(num1,num2):
if num1 < 10 or num2 < 10:
return int(num1*num2)
else:
n = len(str(num1))
a = int(str(num1)[:-(int(n/2))])
#print(a)
c = int(str(num2)[:-(int(n/2))])
#print(c)
b = int(str(num1)[-(int(n/2)):])
#print(b)
d = int(str(num2)[-(int(n/2)):])
#print(d)
val1 = mult(a,c)
val2 = mult(b,d)
val3 = mult(a+b,c+d) - val1 - val2
ans = val1*(10**int(n)) + val2 + (val3)*(10**(int(n/2)))
return int(ans)
I will add any additional info needed, please let me know
Any help in this regards is much appreciated
Thank you
In found a working example of the Karatsuba algorithm:
https://pythonandr.com/2015/10/13/karatsuba-multiplication-algorithm-python-code/
I think your problem is that you cannot handle odd n in this way. For example multiplying 100 with 100: If you round 1.5 to 2 you get 100 000 a zero to much and if your round it to 1 your get 1000 with a zero missing. Also you should take the max number of digits from both numbers not just num1.
I hope the code below can help you solving your problem:
def karatsuba(x,y):
"""Function to multiply 2 numbers in a more efficient manner than the grade school algorithm"""
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
n = max(len(str(x)),len(str(y)))
nby2 = n / 2
a = x / 10**(nby2)
b = x % 10**(nby2)
c = y / 10**(nby2)
d = y % 10**(nby2)
ac = karatsuba(a,c)
bd = karatsuba(b,d)
ad_plus_bc = karatsuba(a+b,c+d) - ac - bd
# this little trick, writing n as 2*nby2 takes care of both even and odd n
prod = ac * 10**(2*nby2) + (ad_plus_bc * 10**nby2) + bd
return prod
I am doing an exercise of my school book which says :
"Write a code in python which calculates the power of a number without using the function pow()."
The first parts of my function are working fine. But when it comes to # elif b > 1
It just returns the number of a * b, not the a ** b ...
I would be really happy if you could help me with that. I have spent at least 1 hour trying to fix it.
def mypow(a,b):
if b == 0:
return 1
if b == 1:
return a
elif b > 1:
x = 0
for i in range(b):
x += 1 * a
return x
# I know I got to add what happens if the b is negative, but I will do this after fixing the bug.
You appear to be adding instead of multiplying.
for i in range(b):
x *= a
You don't need special cases for 0 and 1; b == 0 is sufficient.
def mypow(a, b):
answer = 1 # a ** 0 == 1
# The loop is only entered if b > 0
for _ in range(b):
answer *= a
return answer
That is probably because you're adding a to x b times. You should multiply, not add.
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))
I am trying to find the great common divisor by using a function and solving it iteratively. Though, for some reason, I am not sure why I am not getting the right output.
The greatest common divisor between 30 & 15 should be 15, however, my output is always giving me the wrong number. I have a strong feeling that my "if" statement is strongly incorrect. Please help!
def square(a,b):
'''
x: int or float.
'''
c = a + b
while c > 0:
c -= 1
if a % c == 0 and b % c == 0:
return c
else:
return 1
obj = square(30,15)
print (obj)
You should return a value only if you finished iterating all numbers and found none of them a divisor to both numbers:
def square(a, b):
c = a + b
while c > 0:
if a % c == 0 and b % c == 0:
return c
c -= 1
return 1
However, the last return will be unneeded in this case, as c would go from a + b to 1, and mod 1 will always bring a common divisor, so the loop will always terminate with 1, for the worst case.
Also, a number greater than a and b can not be a common divisor of them. (x mod y for y > x yields x), and gcd is the formal name for the task, so I would go with
def gcd(a, b):
for c in range(min(a, b), 0, -1):
if a % c == b % c == 0:
return c
for iterational solution.
You might be interested to know that there is a common recursive solution to the GCD problem based on the Euclidian algorighm.
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a % b)
print(gcd(30, 15))
# 15
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