How to make a function which multiplies two values - python

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

Rounding issue with python (implementing Karatsuba's algorithm)

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

Trying to figure out pow source code in python | My function gone wrong

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.

Division using recursion

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))

Finding Greatest Common Divisor through iterative solution (python 3)

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

Calculating logarithm, why is this algorithm not efficient, and how to make it more efficient?

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

Categories

Resources