Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a difference between `0--3//2` and `--3//2`?

I was figuring out how to do floor/ceiling operations without the math module. I solved this by using floor division //, and found out that the negative "gives the ceiling". So this works:

>>> 3//2 1 >>> -3//2 -2 

I would like the answer to be positive, so first I tried --3//2, but this gives 1. I inferred this is because Python evaluates -- to +. So to solve this, I found out I could use -(-3//2)), problem solved.

But I came over another solution to this, namely (I included the previous example for comparison):

>>> --3//2  # Does not give ceiling 1 >>> 0--3//2  # Does give ceiling 2 

I am unable to explain why including the 0 helps. I have read the documentation on division, but I did not find any help there. I thought it might be because of the evaluation order:

If I use --3//2 as an example, from the documentation I have that Positive, negative, bitwise NOT is strictest in this example, and I guess this evaluates -- to +. Next comes Multiplication, division, remainder, so I guess this is +3//2 which evaluates to 1, and we are finished. I am unable to infer it from the documentation why including 0 should change the result.

References:

  • 6.7. Binary arithmetic operations
  • 6.14. Evaluation order
like image 267
Karl Wilhelm Avatar asked Oct 15 '21 10:10

Karl Wilhelm


People also ask

Is 1 the same as 1. 0 Python?

As for why 1.0 == 1 , it's because 1.0 and 1 represent the same number. Python doesn't require that two objects have the same type for them to be considered equal. Or if you want to also accept third-party implementation of Python's integer interface, you can do isinstance(x, numbers. Integral) .

What's the difference between 1 and 1. 0?

Put simply, 1 is an integer, 1.0 is a float.


1 Answers

Python uses the symbol - as both a unary (-x) and a binary (x-y) operator. These have different operator precedence.

In specific, the ordering wrt // is:

  • unary -
  • binary //
  • binary -

By introducing a 0 as 0--3//2, the first - is a binary - and is applied last. Without a leading 0 as --3//2, both - are unary and applied together.

The corresponding evaluation/syntax tree is roughly like this, evaluating nodes at the bottom first to use them in the parent node:

 ---------------- ----------------  |     --3//2     |    0--3//2     | |================|================| |                |    -------     | |                |   | 0 - z |    | |                |    -----+-     | |                |         |      | |     --------   |     ----+---   | |    | x // y |  |    | x // y |  | |     -+----+-   |     -+----+-   | |      |    |    |      |    |    | |  ----+    +--  |   ---+    +--  | | | --3 |  | 2 | |  | -3 |  | 2 | | |  -----    ---  |   ----    ---  |  ---------------- ----------------  

Because the unary - are applied together, they cancel out. In contrast, the unary and binary - are applied before and after the division, respectively.

like image 171
MisterMiyagi Avatar answered Oct 11 '22 19:10

MisterMiyagi