What is meaning of (x,y//2) in python programming - python

Here is the code
def power(x, y):
if y == 0:
return 1
if y % 2 == 0:
return power(x, y // 2) * power(x, y // 2)
return x * power(x, y // 2) * power(x, y // 2)
def order(x):
# Variable to store of the number
n = 0
while (x != 0):
n = n + 1
x = x // 10
return n
def isArmstrong(x):
n = order(x)
temp = x
sum1 = 0
while (temp != 0):
r = temp % 10
sum1 = sum1 + power(r, n)
temp = temp // 10
return (sum1 == x)
x = 153
print(isArmstrong(x))
in function power(x,y) the return statement
return power(x, y // 2) * power(x, y // 2)
what does (x,y//2) mean in this code , I am not able to dry run it.

// means floor division, i.e. it rounds the result down to the nearest whole number
10 // 3 = 3
15 // 7 = 2

The statement will recursively call the power() function again. Here it will first pass x as first argument and y // 2 (// does floor division, it removes the fraction part of fractional/float numbers) as the second argument. Like 5 / 2 = 2.5 BUT 5 // 2 = 2.

// is the floor division operator. The floor division is a division in which only the whole part of the result is given and the fractional part is truncated.
Normal division-
5/2 = 2.5
Floor division-
5//2 = 2

Related

McLaurin series for cosine

I want to make a cosine function that relies on the McLaurin expansion on cosine.. but it doesn't work: it should return me '-1.0..something' but it returns me another value, please can you guys help me??
code:
import math
def _cos(n:float,prec:int):
a = []
k = 0.0
for x in range(prec):
a.append(
((-1)**k)*((n**(2*k+1))/(2*k+1))
)
k+=1
z = 0
for x in a:
z+=x
return z
pi = math.pi
print(_cos(pi,200))
print(math.cos(pi))
As I can see you don't have the good formula.
((-1)**k)*((n**(2*k+1))/(2*k+1))
it's n**(2*n)
then you need to divide it by the factorial of 2n
4! = 4 * 3 * 2 * 1
2n! = 2n * 2n-1 * 2n-2 * 2n-3 ...
your formula of mac laurin is false: see maclaurin cosinus
in your loop, you do a mixture with the pow (x is the pow not k)
your correct code will be:
def _cos(n:float,prec:int):
a = []
for x in range(prec):
a.append(
((-1)**x)*((n**(2*x))/factorial(2*x))
)
z = 0
for x in a:
z+=x
return z
pi = 3.14159265359
print(_cos(pi,200))
print(math.cos(pi))
but if you do that with a precision of 200, you will be an overflow
try with 10 is already best.
i suggest you to use the precicion not from a number of iteration but from the difference between old value and new value like this :
def _cos(n:float,prec:float):
k = 0
cosine_x = 0.0
while True:
old = cosine_x + (pow(-1, k) * pow(n, 2 * k) / factorial(2 * k))
#print(old)
if 0 < abs(old - cosine_x) < prec:
return old
cosine_x = old
k += 1
pi = 3.14159265359
print(_cos(pi,0.000000000000001))
print(cos(pi))
You were not updating k, as you used x for the range and you were missing the factorial function in the division. Try with precison as 20, but 200 is too high.
Try the following code:
import math
def _cos(n:float,prec:int):
a = []
k = 0
for k in range(prec):
a.append(
((-1)**k) * ((n**(2*k))) /
math.factorial(2*k)
)
z = 0
for x in a:
z += x
return z

2 * 2 * 2... j times without the ** operator

I am doing a challenge where I am supposed to calculate 2 * 2 * 2 ... j times, but without using the ** operator.
I tried using square but when I thought about it, it couldn't be squaring.
N = int(input('Num: '))
x = 1
while True:
if x * x > 0:
break
else:
x += 1
print(x - 1 * x - 1)
The result should be 32 if I put in 5 but I actually get -1.
You can bit shift:
N = int(input('Num: '))
print(1 << N)
Or, just use the pow built-in, though it's basically the ** operator:
N = int(input('Num: '))
print(pow(2, N))
If you wanted to use a loop:
N = int(input('Num: '))
result = 1
for _ in range(N):
result *= 2
print(result)
I think you are overcomplicating things:
j = int(input('Num: '))
x = 1
for _ in range(j):
x *= 2
print(x)
or
j = int(input('Num: '))
x = 1
while j > 0:
x *= 2
j -= 1
print(x)
import math
math.pow(x, N)
That should do it!
Edit: math.pow will break for large values of N as described in the comments. Use the solution of Tomothy32 instead.

Karatsuba Multiplication Implementation

I recently implemented Karatsuba Multiplication as a personal exercise. I wrote my implementation in Python following the pseudocode provided on wikipedia:
procedure karatsuba(num1, num2)
if (num1 < 10) or (num2 < 10)
return num1*num2
/* calculates the size of the numbers */
m = max(size_base10(num1), size_base10(num2))
m2 = m/2
/* split the digit sequences about the middle */
high1, low1 = split_at(num1, m2)
high2, low2 = split_at(num2, m2)
/* 3 calls made to numbers approximately half the size */
z0 = karatsuba(low1, low2)
z1 = karatsuba((low1+high1), (low2+high2))
z2 = karatsuba(high1, high2)
return (z2*10^(2*m2)) + ((z1-z2-z0)*10^(m2)) + (z0)
Here is my python implementation:
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m / 2
a = x / 10**(m2)
b = x % 10**(m2)
c = y / 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
My question is about final merge of z0, z1, and z2.
z2 is shifted m digits over (where m is the length of the largest of two multiplied numbers).
Instead of simply multiplying by 10^(m), the algorithm uses *10^(2*m2)* where m2 is m/2.
I tried replacing 2*m2 with m and got incorrect results. I think this has to do with how the numbers are split but I'm not really sure what's going on.
Depending on your Python version you must or should replace / with the explicit floor division operator // which is the appropriate here; it rounds down ensuring that your exponents remain entire numbers.
This is essential for example when splitting your operands in high digits (by floor dividing by 10^m2) and low digits (by taking the residual modulo 10^m2) this would not work with a fractional m2.
It also explains why 2 * (x // 2) does not necessarily equal x but rather x-1 if x is odd.
In the last line of the algorithm 2 m2 is correct because what you are doing is giving a and c their zeros back.
If you are on an older Python version your code may still work because / used to be interpreted as floor division when applied to integers.
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m // 2
a = x // 10**(m2)
b = x % 10**(m2)
c = y // 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
i have implemented the same idea but i have restricted to the 2 digit multiplication as the base case because i can reduce float multiplication in function
import math
def multiply(x,y):
sx= str(x)
sy= str(y)
nx= len(sx)
ny= len(sy)
if ny<=2 or nx<=2:
r = int(x)*int(y)
return r
n = nx
if nx>ny:
sy = sy.rjust(nx,"0")
n=nx
elif ny>nx:
sx = sx.rjust(ny,"0")
n=ny
m = n%2
offset = 0
if m != 0:
n+=1
offset = 1
floor = int(math.floor(n/2)) - offset
a = sx[0:floor]
b = sx[floor:n]
c = sy[0:floor]
d = sy[floor:n]
print(a,b,c,d)
ac = multiply(a,c)
bd = multiply(b,d)
ad_bc = multiply((int(a)+int(b)),(int(c)+int(d)))-ac-bd
r = ((10**n)*ac)+((10**(n/2))*ad_bc)+bd
return r
print(multiply(4,5))
print(multiply(4,58779))
print(int(multiply(4872139874092183,5977098709879)))
print(int(4872139874092183*5977098709879))
print(int(multiply(4872349085723098457,597340985723098475)))
print(int(4872349085723098457*597340985723098475))
print(int(multiply(4908347590823749,97098709870985)))
print(int(4908347590823749*97098709870985))
I tried replacing 2*m2 with m and got incorrect results. I think this has to do with how the numbers are split but I'm not really sure what's going on.
This goes to the heart of how you split your numbers for the recursive calls.
If you choose to use an odd n then n//2 will be rounded down to the nearest whole number, meaning your second number will have a length of floor(n/2) and you would have to pad the first with the floor(n/2) zeros.
Since we use the same n for both numbers this applies to both. This means if you stick to the original odd n for the final step, you would be padding the first term with the original n zeros instead of the number of zeros that would result from the combination of the first padding plus the second padding (floor(n/2)*2)
You have used m2 as a float. It needs to be an integer.
def karat(x,y):
if len(str(x)) == 1 or len(str(y)) == 1:
return x*y
else:
m = max(len(str(x)),len(str(y)))
m2 = m // 2
a = x // 10**(m2)
b = x % 10**(m2)
c = y // 10**(m2)
d = y % 10**(m2)
z0 = karat(b,d)
z1 = karat((a+b),(c+d))
z2 = karat(a,c)
return (z2 * 10**(2*m2)) + ((z1 - z2 - z0) * 10**(m2)) + (z0)
Your code and logic is correct, there is just issue with your base case. Since according to the algo a,b,c,d are 2 digit numbers you should modify your base case and keep the length of x and y equal to 2 in the base case.
I think it is better if you used math.log10 function to calculate the number of digits instead of converting to string, something like this :
def number_of_digits(number):
"""
Used log10 to find no. of digits
"""
if number > 0:
return int(math.log10(number)) + 1
elif number == 0:
return 1
else:
return int(math.log10(-number)) + 1 # Don't count the '-'
The base case if len(str(x)) == 1 or len(str(y)) == 1: return x*y is incorrect. If you run either of the python code given in answers against large integers, the karat() function will not produce the correct answer.
To make the code correct, you need to change the base case to if len(str(x) < 3 or len(str(y)) < 3: return x*y.
Below is a modified implementation of Paul Panzer's answer that correctly multiplies large integers.
def karat(x,y):
if len(str(x)) < 3 or len(str(y)) < 3:
return x*y
n = max(len(str(x)),len(str(y))) // 2
a = x // 10**(n)
b = x % 10**(n)
c = y // 10**(n)
d = y % 10**(n)
z0 = karat(b,d)
z1 = karat((a+b), (c+d))
z2 = karat(a,c)
return ((10**(2*n))*z2)+((10**n)*(z1-z2-z0))+z0

Python function returning first value twice

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

Why do these two implementations of expmod differ for large values?

I've written out a couple of functions for doing expmod, that is, (x ** y) % n. These are both standard functions, I've checked and re-checked both but can't find any silly errors.
Here's the recursive one:
def expmod(x,y,m):
if y == 0: return 1
if y % 2 == 0:
return square(expmod(x,y/2,m)) % m # def square(x): return x*x
else:
return (x * expmod(x,y-1,m)) % m
...and here's the non-recursive one:
def non_recursive_expmod(x,y,m):
x = x % m
y = y % m
result = 1
while y > 0:
if(y%2 == 1):
result = (result * x) % m
x = (x*x) % m
y = y/2
return result
They agree for small values:
>>> expmod(123,456,789) - non_recursive_expmod(123,456,789)
0
...but don't for larger ones:
>>> expmod(24354321,5735275,654) - non_recursive_expmod(24354321,5735275,654)
-396L
What's going on?
Your function non_recursive_expmod has some suspicious steps in it: Remove the %m for x and y at the beginning. Both are not needed.
Additionally make sure that the division of y is an integer division by using y = y // 2.
In total the function should look like this:
def non_recursive_expmod(x, y, m):
result = 1
while y > 0:
if y % 2 == 1:
result = (result * x) % m
x = (x * x) % m
y = y // 2
return result
Non recursive does not decrease y in case it is odd, and even part needs else in case y == 1

Categories