Modulo and order of operation in Python - python

In Zed Shaw's Learn Python the Hard Way (page 15-16), he has an example exercise
100 - 25 * 3 % 4
the result is 97 (try it!)
I cannot see the order of operations that could do this..
100 - 25 = 75
3 % 4 = 0
or (100-25*3) =225 % 4 = ??? but anyhow not 97 I don't think...
A similar example is 3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6 which yields 7
In what order are the operations done?

For the first example: * and % take precedence over -, so we first evaluate 25 * 3 % 4. * and % have the same priority and associativity from left to right, so we evaluate from left to right, starting with 25 * 3. This yields 75. Now we evaluate 75 % 4, yielding 3. Finally, 100 - 3 is 97.

Multiplication >> mod >> subtraction
In [3]: 25 * 3
Out[3]: 75
In [4]: 75 % 4
Out[4]: 3
In [5]: 100 - 3
Out[5]: 97
Multiplication and modulo operator have the same precedence, so you evaluate from left to right for this example.

I figured out the answer to your second question because it was bugging me too--Zac's response is close, but the loss of the result of 1/4 is because of Python 2.X is truncating integer division results. So it's evaluating the modulo operation first, then the division (which since it isn't float, is returned as 0.
3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
3 + 2 + 1 - 5 + (0) - (0) + 6
6 - 5 + 6
1 + 6
7

Here's how it goes:
'*' and '%' have the same precendence, so evaluate those from left to right.
25*3 = 75
75 % 4 = 3 (4*18 = 72; remainder is 3)
100 - 3 = 97
Q.E.D.

Original problem: 100 - 25 * 3 % 4
Actually, evaluating 25 * 3 and taking 75% of 4 is incorrect, and happened to work out conveniently for this problem.
What the % in python actually is is a modulus operator where x % y gives the remainder of x / y. In this case, what happened was that 75 / 4 is 18, with a remainder of 3, which is why 100 - 3 = 97.
Do not try to multiply the percentages, it's a common mistake.

In the second exampe, %has same order as * so we get 3+2+1-5+4%2-1/4+6=
3+2+1-5+(4%2)-(1/4)+6=1+(4%2)-(1/4)+6
=1+0-(1/4)+6=1-(1/4)+6=0.75+6=6.75 and that is what it says when I try it on the console, so whatever you did you must have done something to round it.

Mathematics isn't my strong point, so yes this question got me as well, for a moment. But hope you find this useful.
75 divided by 4 is 18.75
18 multiplied by 4 is 72 (leaving 3 remaining from the 75)
The calculation given is 100-25*3%4 with an answer of 97. Now this is how I would get it using PEMDAS as he speaks of in the question section:
#!/bin/python
A = 100
B = 25
C = 3
D = 4
E = B*C # 75
F = E%D # 3
G = A-F # 97
print("B * C ="), E
print("E % D ="), F
print("A - F ="), G
I think you have to treat modulo (%) as a division,

Python evaluates % after * but before + or _ .
So,
(100 - 25 * 3 % 4)
(100 - 75 % 4)
(100 - 3)
(97)

Related

Python - How can I line up the equals sign of all my equations?

Currently in maths class we are working on gcd and I have written a Python script on my NumWorks calculator.
Here is the code I already wrote :
def div(n):
return [x for x in range(1,n+1) if n%x==0]
def pgcd(x,y):
a = x
b = y
while b > 0:
reste = a % b
print(a, "=", a//b, "*", b, "+", a%b)
a,b = b,reste
return "PGCD("+str(x)+";"+str(y)+") = " + str(a)
And it ouputs this :
pgcd(178,52)
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
I want it to output that :
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
I've read many articles online but I have no idea how to put that into my code.
Thanks in advance.
You can use the rjust string method.
The thing is you need to figure out what is the widest string on the left hand side you will print. Luckily here, it would be the first value.
So I would go with this.
def pgcd(x,y):
a = x
b = y
len_a = len(f"{a}")
while b > 0:
reste = a % b
print(f"{a}".rjust(len_a), "=", a//b, "*", b, "+", a%b)
a,b = b,reste
return "PGCD("+str(x)+";"+str(y)+") = " + str(a)
Should print this.
>>> pgcd(178,52)
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
'PGCD(178;52) = 2'
See .format for strings. An example of right justifying would look something like print('{:>6}'.format(42))
You can also use rjust
Use str.format() to achieve this:
'{0: >{width}}'.format(178, 3)
'{0: >{width}}'.format(52, 3)
Will output
178
52
Ok I asked it on a Discord server and they found out so if anyone is having the same problem as me here is the solution (did not put all code for space) :
def pgcd(x,y):
a = x
b = y
maxi = len(str(a))
while b > 0:
reste = a % b
print(" "*(maxi-len(str(a))),a, "=", a//b, "*", b, "+", a%b)
Basically compare to original code we added a maxi variable that has the maximum lenght of my integers, and then if the int is smaller like 8 compare to 178 we add to spaces because the difference of their length is 2.
This explanation is probably not 100% correct but it helps getting an idea.

Karatsuba RecursionError: maximum recursion depth exceeded while calling a Python object

I am trying to implement Karatsuba multiplication on Python.
The inputs are two integers of length power of 2. They are of same length.
def mult(x,y):
if int(x) < 10 and int(y) <10:
return int(x)*int(y)
x_length = len(str(x))//2
y_length = len(str(y))//2
a = str(x)[:x_length]
b = str(x)[x_length:]
c = str(y)[:y_length]
d = str(y)[y_length:]
n = len(a) + len(b)
m = n//2
return 10**n* mult(a,c) + 10**m*(mult(a+b, c+d)-mult(a,c)-mult(b,d)) + mult(b,d)
Running
mult(1234,5678)
This gives the following error:
if int(x) < 10 and int(y) <10:
RecursionError: maximum recursion depth exceeded while calling a Python object
However if I do
def mult(x,y):
if int(x) < 10 and int(y) <10:
return int(x)*int(y)
x_length = len(str(x))//2
y_length = len(str(y))//2
a = str(x)[:x_length]
b = str(x)[x_length:]
c = str(y)[:y_length]
d = str(y)[y_length:]
n = len(a) + len(b)
m = n//2
return 10**n* mult(a,c) + 10**m*(mult(a,d)+mult(b,c)) + mult(b,d)
So I am doing 4 recursions in the last line (i.e. mult(a,c), mult(a,d), mult(b,c), mult(b,d)) rather than 3 as in the above (i.e. mult(a,c), mult(a+b, c+d), mult(b,d)).
Then it turns out ok.
Why is this happening? And how can I do it with only 3 recursions?
a, b, c, d are strings. String addition is concatenation. "1" + "2" is "12". So what is passed to mult(a+b, c+d) is not what you intended to pass.
TL;DR.
First thing first, the recursion is supposed to terminate quickly. Let's see why it doesn't. Add print x, y at the beginning of mult:
def mult(x, y):
print x, y
....
and redirect the output into a file. The result is surprising:
1234 5678
12 56
1 5
12 56
1 5
12 56
1 5
12 56
1 5
....
No wonder the stack overflows. Question is, why we repeat the 12 56 case? Let's add more instrumentation, to find out which recursive call does that:
def mult(x,y,k=-1):
....
print a, b, c, d
ac = mult(a, c, 0)
bd = mult(b, d, 2)
return 10**n* ac + 10**m*(mult(a+b, c+d, 1) - ac - bd) + bd
The results are
-1 : 1234 5678
12 34 56 78
0 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
You can see that the recursive call marked 1 always gets 12 56. It is the call which computes mult(a + b, c + d). Oh well. All of them a, b, c, d are strings. "1" + "2" is "12". Not exactly what you've meant.
So, make up your mind: are the parameters integer or strings, and treat them accordingly.
Note that in your first code snippet - you are calling your function not thrice, but 5 times:
return 10**n* mult(a,c) + 10**m*(mult(a+b, c+d)-mult(a,c)-mult(b,d)) + mult(b,d)
I can't really say for the rest of your code, but taking a quick look at the Wikipedia entry on Karatsuba, you can decrease your recursion depth by increasing the base number you are using (i.e. from 10 to 100 or 1000). You can change your recursion depth using sys.setrecursionlimit but python stack frames can get quite big, so try to avoid doing so as it may be dangerous.

How to find 2 to the power of an insanely big number modulo 10^9

I have an excessively big number (1500+) digits and I need to find 2 ** that number modulo 1_000_000_000 so I wrote this python:
n = 1
return_value = 2
while n < To_the_power_of:
return_value *= 2
return_value = return_value % 1_000_000_000
n += 1
This returns the correct value for smaller values, but takes too long for bigger values.
If the number is modulo 10 then you get this pattern which could be used.
2 ** 1 modulo 10 = 2
2 ** 2 modulo 10 = 4
2 ** 3 modulo 10 = 8
2 ** 4 modulo 10 = 6
2 ** 5 modulo 10 = 2
2 ** 6 modulo 10 = 4
2 ** 7 modulo 10 = 8
2 ** 8 modulo 10 = 6
I'm hoping that a similar pattern could be used to answer the original problem.
You already know that the sequence will repeat. You found the cycle of 4 for mod 10; now, just find it for a billion:
mod_billion = set()
pow_2 = 2
billion = 10**9
while pow_2 not in mod_billion:
mod_billion.add(pow_2)
pow_2 *= 2
if pow_2 > billion:
pow_2 -= billion
print (pow_2, len(mod_billion))
Three seconds later, we get:
512 1562508
Thus, this sequence repeats every 1562508 items. To find your value for your given power:
cycle = 1562508
small_power = big_power % cycle
result = (2 ** small_power) % billion
Your code makes about 10 ** 1500 iterations, which is indeed insanely long. A useful general technique is exponentiation by squaring, which will give you the result in about 4500 iterations.
If you want to follow the path of the #Prune's answer, you should go along the lines of Fermat's Little Theorem, specifically the Euler's generalization. phi(1_000_000_000) is easy to compute, because 10 ** 9 = (2 ** 9) * (5 ** 9), the product of 2 powers of primes.

Ulam Spiral (for diagonal numbers) writing program python

I am writing a code the represent the Ulam Spiral Diagonal Numbers and this is the code I typed myself
t = 1
i = 2
H = [1]
while i < 25691 :
for n in range(4):
t += i
H.append(t)
i += 2
print(H)
The number "25691" in the code is the side lenght of the spiral.If it was 7 then the spiral would contain 49 numbers etc.
Here H will give you the all numbers in diagonal. But I wonder is there a much faster way to do this.
For example if I increase the side lenght large amount it really takes forever to calculate the next H.
Code Example:
t = 1
i = 2
H = [1]
for j in range(25000,26000):
while i < j :
for n in range(4):
t += i
H.append(t)
i += 2
For example my computer cannot calculate it so, is there a faster way to do this ?
You dont need to calculate the intermediate values:
Diagonal, horizontal, and vertical lines in the number spiral correspond to polynomials of the form
where b and c are integer constants.
wikipedia
You can find b and c by solving a linear system of equations for two numbers.
17 16 15 14 13
18 5 4 3 12 ..
19 6 1 2 11 28
20 7 8 9 10 27
21 22 23 24 25 26
Eg for the line 1,2,11,28 etc:
f(0) = 4*0*0+0*b+c = 1 => c = 1
f(1) = 4*1*1+1*b+1 = 2 => 5+b = 2 => b = -3
f(2) = 4*2*2+2*(-3)+1 = 11
f(3) = 4*3*3+3*(-3)+1 = 28

Arithmetic in python, can't figure out simple basic operations

I am doing some very basic excersizes in python. I'm using the hard way to learn python book, which in excersize 3 have a expression I should understand.
3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6, is coming out as 7.
For me, the answer is 6.
6 - 5 + 0 - 1 / 4 + 6
1 - 1 / 4 + 6
6.
This is clearly wrong, but can anyone help me with priorty in mathematics etcetera? I seem to have forgotten everything if it's not inside a parenthesis!
EDIT: Thank you very much for the response. I've clearly learned something about the very basic stuff, which I think is important before moving on! My order of operations was definately way off!
4 % 2 = 0 because the remainder of 4 / 2 is 0
1 / 4 is also 0 because it is doing integer division and .25 is floored to 0.
If we look at the rules for Operator precedence in Python we can see that:
3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
is being treated as:
3 + 2 + 1 - 5 + (4 % 2) - (1 / 4) + 6
(For the arithmetic operators this is the same order as the standard order of operations in mathematics.)
Now 4 % 2 is 0 since the remainder when dividing 4 by 2 is 0. 1 / 4 is also 0 as Python will return a value of the same type as the operands and 0.25 when "floored" is 0.
So I think your mistake is applying the / to the whole expression to the left. In fact as / has a higher precedence than - the division evaluated is 1 / 4.
See the table of operator precedences in Python.
http://docs.python.org/reference/expressions.html#summary
1/4 rounds down (or floors) to 0 since 1 and 4 are integers.
Therefore 1-0+6 = 7
You seem to think that python should evaluate everything to the left of a / operator before dividing by the first token to the right. That would be an odd evaluation order by any measure.
As always with programming: if you have a complex expression with infix operators, use brackets to force the correct order.
In Python3.x it'd be 6.75 b/c 1/4 = 0.25 (true division). However, in Python 2.x 1/4 = 0 (convert to the most generic type of the arguments used, that is int in given case). Therefore, if it'd be 1. / 4 or 1 / 4. then in Python2.x you'd get 0.25 and the result would be 6.75
Priority is for division and multiplication, if you don't use brackets!
In this way: 1-1/4+6=7 because 1/4, working with integer, is = 0
operands are integer, so 1/4 integer dividing = 0
Rather than mathematics you should have a look at the operators:
a%b is a modular b, which in case of a=4 and b=2 yields 0 (ok, thanks mathematics ;) )
1/4: here it's important to take into account that 1 and 4 are integers. So the result will also be an integer, i.e. 0.25 becomes 0.
That's why you end up with
3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
= 3 + 2 + 1 - 5 + 0 - 0 + 6
= 7
For operators in python have a look at the python docs.
3 + 2 + 1 - 5 + 4 % 2 - 1 / 4 + 6
The order of precedence for this is multiplication and division evaluated left to right and then addition and subtraction. So..
3 + 2 + 1 - 5 + (4 % 2) - (1 / 4) + 6
The ones inside the parentheses are evaluated first because of order of operations. Because you only have integers present (and not a float which would allow the value 0.25), 1/4 will floor to 0 because of python.
3 + 2 + 1 - 5 + 0 - 0 + 6
Afterwards, when you evaluate from left to right for addition/subtraction, you are left with:
6 - 5 + 6 => 1 + 6 => 7
Remember that division and multiplication are evaluated before addition and subtraction. For more information, Order of Operations - Wikipedia

Categories