Codementor Events

Python’s arithmetic is weird: 1 +-+-+ 1 == 2

Published Oct 26, 2023
Python’s arithmetic is weird: 1 +-+-+ 1 == 2

All programming languages have some quirks and strange behavior.
Python is certainly no exception.
I was quite surprised recently when I found out that Python allows multiple + and - in a row.

>>> 1 +-+-+ 1
2

That's right!
This is valid arithmetic in Python.

Now you may think that you can safely stick it into your next commit at work to stump your code reviewer.
Before you do, let me show you that it does not always behave as expected.

Use as many + and - together as you want

When using multiple + or - operators in a row, it's as though the operators are replaced with * (+1) and * (-1) respectively:

>>> 1 +++++++ 1
2
>>> 1 ++++++++++++++++++++ 1
2
>>> 1 ------- 1
0
>>> 1 ------ 1
2

Please let me know if you know of another programming language that behaves like this or if you know the purpose for it.
The only use case that I can think of is if you need to ask "help" from a fellow developer to deal with your annoying manager:

my_need = 1 --- +++ --- 5

There is always someone familiar with morse code in movies so it might work.

Using multiple - with // is weird

In case you don't know, the // operator performs a division like / but instead returns an integer.

>>> 5 // 2
2
>>> assert 5 // 2 == math.floor(5 / 2)
True

Now let's look at this simple calculation using //:

>>> 2 + 5 // 2
4

Nothing ground breaking here.
Python calculates 5 // 2 before performing the addition.

Let's use the newly discovered feature of Python's arithmetic by replacing + with --.
What could go wrong?

>>> 2 -- 5 // 2
5

What is going on here?
Is Python broken?
Are mathematics failing us?

Let's break this down to understand what is happening:

>>> 2 - (-5 // 2)
5
>>> -5 // 2
-3
>>> math.floor(-5 / 2)
-3

The description of the floor() function from the standard library documentation explains this result:

Return the floor of x, the largest integer less than or equal to x.

Now it all makes sense.
The largest integer less than or equal to -2.5 is -3.
So the unexpected result of 2 -- 5 // 2 is due to the order of operations in Python.

The operator precedence in Python gives the determination of the sign a higher precedence than the // operator.
This is why the negative sign is applied to 5 before 5 // 2 is performed.

Now it's all clear and nothing else will surprise us, right?

Adding a + into the mix is even weirder

Now let's add a + sign to our previous example because why not!

>>> 2 +-- 5 // 2
4
>>> 2 -+- 5 // 2
5
>>> 2 --+ 5 // 2
5

Right now might be a good time to open your Python interpreter and verify that this is for real because you probably don't believe it.

It's as though the + doesn't do anything in -+- and --+ compared to using -- in the previous section.
On the other hand the result is different with +--.
Why is that?

>>> 2 + ((-(-5)) // 2)
4
>>> 2 + ((+5) // 2)
4
>>> 2 - ((+(-5)) // 2)
5
>>> 2 - ((-(+5)) // 2)
5
>>> 2 - ((-5) // 2)
5

Once again the operator precedence clarifies this surprising behavior.
Except for the most left sign, all the signs are combined and assigned to the value on the right, e.g. 5.
The most left operator is kept for the addition or subtraction operation.
Hence why -+- and --+ give identical results.

It means that +-- is not equivalent to * (+1) * (-1) * (-1) but instead is equivalent to + ((-1) * (-1))
The results are the same for the two rewrites of +-- except with the floor function due to its sensitivity to the sign of its argument.

Never use multiple + or - operators!

Being able to use multiple + and - operators in a row is most likely a side effect rather than an intended feature in Python.
In any case I would strongly recommend to refrain from using this feature, even just for the fun.
Most of the time it works as if + and - could be replaced by * (+1) and * (-1) respectively but at least for the operator // this is just not the case.

However using this quirk of Python was a nice way to learn and explore the operator precedence!


Thank you to Quinn Blenkinsop for reviewing this post and providing very useful feedback.

Discover and read more posts from Anthony Hillairet
get started
post comments1Reply
lucas brown
a year ago

no, its not wired but its kind a fun. In Python, the expression 1 ±±+ 1 evaluates to 2 because of the way Python’s interpreter handles the plus and minus operators in sequence.

Let’s break down the expression step by step:

1 is a positive integer.

  • is the unary minus operator, which negates the sign of the number that follows it. So, -1 results in -1.
  • is the binary plus operator, which adds two numbers together. So, -1 + 1 results in 0.
  • is the unary minus operator again, which negates the sign of the number that follows it. So, -0 results in 0.
  • is the binary plus operator again, and adding 0 to 1 results in 1.
    Finally, - is the unary minus operator again, and negating 1 results in -1.
    So, the expression 1 ±±+ 1 effectively simplifies to -1, and that’s why it evaluates to 2.

It’s important to note that while this expression may appear to be weird or confusing at first glance, it follows the well-defined rules of Python’s operator precedence and association. This is not unique to Python and can be found in other programming languages as well.