Why is i++++++++i valid in python? - python

I "accidentally" came across this weird but valid syntax
i=3
print i+++i #outputs 6
print i+++++i #outputs 6
print i+-+i #outputs 0
print i+--+i #outputs 6
(for every even no: of minus symbol, it outputs 6 else 0, why?)
Does this do anything useful?
Update (Don't take it the wrong way..I love python):
One of Python's principle says
There should be one-- and preferably only one --obvious way to do it. It seems there are infinite ways to do i+1

Since Python doesn't have C-style ++ or -- operators, one is left to assume that you're negating or positivating(?) the value on the left.
E.g. what would you expect i + +5 to be?
i=3
print i + +(+i) #outputs 6
print i + +(+(+(+i))) #outputs 6
print i + -(+i) #outputs 0
print i + -(-(+i)) #outputs 6
Notably, from the Python Grammar Specification, you'll see the line:
factor: ('+'|'-'|'~') factor | power
Which means that a factor in an expression can be a factor preceded by +, -, or ~. I.e. it's recursive, so if 5 is a factor (which it is because factor->power->NUMBER), then -5 is a factor and so are --5 and --------5.

The plus signs are considered unary operators to the right most i variable, as in +(-3) = -3, or +(+(+3))) = 3. Just the left most sign (plus or minus) are parsed as binary, so i+++i = i + (+(+i)), which translates to i + i = 3 + 3 = 6, in your example.
The other expressions follow the same principle.

That should read
print i + (+ (+i) )
that is, the first sign is the addition operator, the other ones are infix signs
+i
and (unfortunately)
++i
are thus valid statements.

Related

How to I find the last three digits of a number that is the result of 2^(a^b)

In Python, I am trying to figure out how to find the last three digits of a number that is the result of 2^(a^b) with a and b as the imput values. It handles input values up to 6, 6 without slowing down, but once it gets to 7, 7 it becomes very slow, and 8, 8 just doesnt work. I was wondering if there was some kind of mathematical shortcut or something to get the last three digits faster. Also, I am kind of new to stack overflow, so I don't know if I am asking this in the right place. Also, I am using replit if that changes anything. (This is for school and I would really appreciate help)
def last_three(a, b):
num = 2 ** (a ** b)
string = str(num)
length = len(string)
print (length)
new_string = ''
new_string += string[length - 3]
new_string += string[length - 2]
new_string += string[length - 1]
return int(new_string)
I realized that the equation is not the slow part, it was the fact that I was converting it to a string, finding the length, and indexing the last 3 digits.
One of the comments told me to do 2**(a**b) % 1000 to get the solution, and it worked.
Thank you all for the feedback.

Compare two strings containing "expressions" for equality

I have two strings, the one is "K <- L * 5" and the other is "K <- 5 * L"
Is there a way to say in Python 3 to compare these and return True ? ( because they are the same but in different order )
I'm looking for a solution to compare only the 2nd part, after <-
Specifically I'd like the second part to give the same result.
E.g.
"5 % 3" and "3 % 5" are not the same
"L * 5" and "5 * L" are the same
Maybe a dictionary could help, but I'm not familiar with Python.
As explained in the comments, the check of semantics in this is an obstacle. You could probably build your own (or find someone else's) grammatical parser for these kind of mathematical expressions.
A workaround would be to use the mathematical capability that is already built in and converting the expression to valid expressions. I chose here to convert all numbers and letters to their Ascii equivalent. You can choose yourself how picky you want to be in the conversion (lower all caps, use only certain alphabets etc...) but here is a working example.
def main():
opt1_raw = "K <- N * 5"
opt2_raw = "K <- 5 * N"
opt1 = opt1_raw.split("<-")[1]
opt2 = opt2_raw.split("<-")[1]
ascii_exp = ''.join([str(ord(char)) if char.isdigit() or char.isalpha() else char for char in opt1])
s = eval(ascii_exp)
ascii_exp = ''.join([str(ord(char)) if char.isdigit() or char.isalpha() else char for char in opt2])
p = eval(ascii_exp)
print(opt1 +" and " + opt2 +": " + str(s==p))
main()
In the loop, I am converting all digits and alphas (letters) to their ascii equivalent, letting operators such as '*' and '/' be where they are. Then I use eval() to let python evaluate the expression. The result of an evaluation can then look like this: 76*53 instead of "L*5" Then I just compare the result. I'm sure you can find a more elegant way to incorporate this but its an example of evaluating such abstract expressions.
The output:
L*5 and 5*L: True
L*5 and 5 % 3: False
5 % 3 and 3 % 5: False
L*5 and 5 % 3: False

simple for loop needing explained

I know this is going to sound silly but I cannot for the life of me figure out the logic behind how this for loop returns 13,11,9,7.
for i in range(13,5,-1):
if i % 2 != 0:
print i
I know the first value is the number it starts with, the second is where it stops, and the third being the steps it takes. The "if i % 2 !=0:" is what is throwing me off. Can anybody explain what is happening for me?
the first bit is the range(13,5,-1) which just counts backwards from 13 to 6. The next bit is i%2 != 0. i%2 == 0 is equivalent to saying if even, or "if this number can be divided by 2 with no remainder", so your statment is saying "if odd" (which is obviously the same as "if not even").
Basically, the loop is printing odd numbers starting at 13 and decreasing down to 6 (but 6 is even, so it doesn't get printed)
% is the modulo operator. From the docs:
The % (modulo) operator yields the remainder from the division of the
first argument by the second. The numeric arguments are first
converted to a common type. A zero right argument raises the
ZeroDivisionError exception. The arguments may be floating point
numbers, e.g., 3.14%0.7 equals 0.34 (since 3.14 equals 4*0.7 + 0.34.)
The modulo operator always yields a result with the same sign as its
second operand (or zero); the absolute value of the result is strictly
smaller than the absolute value of the second operand.
if i % 2 !=0
That line means "if the remainder after dividing i by 2 is not equal to 0," so it's checking to see if i is odd. The for loop is counting down by 1, but the if statement skips printing the even numbers.

Modulo for negative dividends in Python [duplicate]

This question already has answers here:
How does the modulo (%) operator work on negative numbers in Python?
(12 answers)
Closed last month.
Been looking through other answers and I still don't understand the modulo for negative numbers in python
For example the answer by df
x == (x/y)*y + (x%y)
so it makes sense that (-2)%5 = -2 - (-2/5)*5 = 3
Doesn't this (-2 - (-2/5)*5) =0 or am I just crazy?
Modulus operation with negatives values - weird thing?
Same with this
negative numbers modulo in python
Where did he get -2 from?
Lastly if the sign is dependent on the dividend why don't negative dividends have the same output as their positive counterparts?
For instance the output of
print([8%5,-8%5,4%5,-4%5])
is
[3, 2, 4, 1]
In Python, modulo is calculated according to two rules:
(a // b) * b + (a % b) == a, and
a % b has the same sign as b.
Combine this with the fact that integer division rounds down (towards −∞), and the resulting behavior is explained.
If you do -8 // 5, you get -1.6 rounded down, which is -2. Multiply that by 5 and you get -10; 2 is the number that you'd have to add to that to get -8. Therefore, -8 % 5 is 2.
In Python, a // b is defined as floor(a/b), as opposed to most other languages where integer division is defined as trunc(a/b). There is a corresponding difference in the interpretation of a % b = a - (a // b) * b.
The reason for this is that Python's definition of the % operator (and divmod) is generally more useful than that of other languages. For example:
def time_of_day(seconds_since_epoch):
minutes, seconds = divmod(seconds_since_epoch, 60)
hours, minutes = divmod(minutes, 60)
days, hours = divmod(hours, 24)
return '%02d:%02d:%02d' % (hours, minutes, seconds)
With this function, time_of_day(12345) returns '03:25:45', as you would expect.
But what time is it 12345 seconds before the epoch? With Python's definition of divmod, time_of_day(-12345) correctly returns '20:34:15'.
What if we redefine divmod to use the C definition of / and %?
def divmod(a, b):
q = int(a / b) # I'm using 3.x
r = a - b * q
return (q, r)
Now, time_of_day(-12345) returns '-3:-25:-45', which isn't a valid time of day. If the standard Python divmod function were implemented this way, you'd have to write special-case code to handle negative inputs. But with floor-style division, like my first example, it Just Works.
The rationale behind this is really the mathematical definition of least residue. Python respects this definition, whereas in most other programming language the modulus operator is really more like a 'reaminder after division' operator. To compute the least residue of -5 % 11, simply add 11 to -5 until you obtain a positive integer in the range [0,10], and the result is 6.
When you divide ints (-2/5)*5 does not evaluate to -2, as it would in the algebra you're used to. Try breaking it down into two steps, first evaluating the part in the parentheses.
(-2/5) * 5 = (-1) * 5
(-1) * 5 = -5
The reason for step 1 is that you're doing int division, which in python 2.x returns the equivalent of the float division result rounded down to the nearest integer.
In python 3 and higher, 2/5 will return a float, see PEP 238.
Check out this BetterExplained article and look # David's comment (No. 6) to get what the others are talking about.
Since we're working w/ integers, we do int division which, in Python, floors the answer as opposed to C. For more on this read Guido's article.
As for your question:
>>> 8 % 5 #B'coz (5*1) + *3* = 8
3
>>> -8 % 5 #B'coz (5*-2) + *2* = -8
2
Hope that helped. It confused me in the beginning too (it still does)! :)
Say -a % b needs to be computed. for ex.
r= 11 % 10
find the next number after 11 that is perfectly divisible by 10 i.e on dividing that next number after 11 gives the remainder 0.
In the above case its 20 which on dividing by 10 gives 0.
Hence, 20-11 = 9 is the number that needs to be added to 11.
The concept if 60 marbles needs to be equally divided among 8 people, actually what you get after dividing 60/8 is 7.5 since you can'nt halve the marbles, the next value after 60 that is perfectly divisible by 8 is 64. Hence 4 more marbles needs to be added to the lot so that everybody share the same joy of marbles.
This is how Python does it when negatives numbers are divided using modulus operator.

Why does 1+++2 = 3?

How does Python evaluate the expression 1+++2?
How many ever + I put in between, it is printing 3 as the answer. Please can anyone explain this behavior
And for 1--2 it is printing 3 and for 1---2 it is printing -1
Your expression is the same as:
1+(+(+2))
Any numeric expression can be preceded by - to make it negative, or + to do nothing (the option is present for symmetry). With negative signs:
1-(-(2)) = 1-(-2)
= 1+2
= 3
and
1-(-(-2)) = 1-(2)
= -1
I see you clarified your question to say that you come from a C background. In Python, there are no increment operators like ++ and -- in C, which was probably the source of your confusion. To increment or decrement a variable i or j in Python use this style:
i += 1
j -= 1
The extra +'s are not incrementors (like ++a or a++ in c++). They are just showing that the number is positive.
There is no such ++ operator. There is a unary + operator and a unary - operator though. The unary + operator has no effect on its argument. The unary - operator negates its operator or mulitplies it by -1.
+1
-> 1
++1
-> 1
This is the same as +(+(1))
1+++2
-> 3
Because it's the same as 1 + (+(+(2))
Likewise you can do --1 to mean - (-1) which is +1.
--1
-> 1
For completeness there is no * unary opeartor. So *1 is an error. But there is a **
operator which is power of, it takes 2 arguments.
2**3
-> 8
1+(+(+2)) = 3
1 - (-2) = 3
1 - (-(-2)) = -1
Trying Unary Plus and Unary minus:
The unary - (minus) operator yields the negation of its numeric argument.
The unary + (plus) operator yields its numeric argument unchanged.
>>> +2
2
>>> ++2
2
>>> +++2
2
>>> -2
-2
>>> --2
2
>>> ---2
-2
>>> 1+(++2)
3
I believe it's being parsed as, the first + as a binary operation (add), and the rest as unary operations (make positive).
1 + (+(+2))
Think it as 1 + (+1*(+1*2))). The first + is operator and following plus signs are sign of second operand (= 2).
Just like 1---2 is same as 1 - -(-(2)) or 1- (-1*(-1*(2))

Categories