0

What does it mean when you have something like n // float(m) with division imported from __future__?

Ex:

>>> x = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
>>> y = [2.0 // v for v in x]​
>>> print y
[19.0, 9.0, 6.0, 4.0, 4.0, 3.0, 2.0, 2.0, 2.0, 2.0]

2.0 / 0.1 should yield a 20.0, but I got 19 using //

2.0 / 0.2 is normally a 10, but got a 9

2 / 0.4 is 5. Got 4

Ok... So it looks like it subtracts 1 from the usual answer if it could be an integral type. But then you get to the last one...

2.0 // 1.0 gives 2.0. Same as 2.0 / 1.0...

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Alex
  • 3,111
  • 6
  • 27
  • 43
  • `a // b == floor(a/b)` (see [PEP 328](http://legacy.python.org/dev/peps/pep-0238/), section "Semantics of Floor Division"), and since `a/b` happens first, you're running into the inexactness of floating points. –  Sep 26 '14 at 15:11
  • There is actually an ongoing discussion on whether you should get a `float` or an `int` back. See http://bugs.python.org/issue22444 – roippi Sep 26 '14 at 15:15
  • Yeah, but 2.0 / 0.1 is still 20.0. `math.floor(20.0)` should still be 20.0, not 19.0. Right? – Alex Sep 26 '14 at 15:18
  • @AlexYan That's what's my comment is about: 0.1 isn't exactly representable in floating point. 2.0, however, is, and so is 0.5 (and 1.0, as in your example). So try `2.0 // 0.5`, it will yield `4.0`. –  Sep 26 '14 at 15:19
  • Yes I understand that the number of bits in a floating point may not be enough to represent certain numbers. But then why is it that `math.floor(2.0 / 0.1)` yields a 20.0, while `20.0 // 0.1` yields a 19.0? They're said to be equivalent aren't they? That's what I was trying to say – Alex Sep 26 '14 at 16:21
  • Ok here's where we are right now: 0.1 is about 0.10000000149011612 as a double. 20 divided by that is about 19.99999970197678, which results in a 19 after being floored. BUT what I meant to say earlier is... Why is it that `math.floor(2.0 / 0.1)` produced a 20, while `20.0 // 0.1` produced a 19? Why is one of the 0.1s being rounded off while the other one is preserved? – Alex Sep 28 '14 at 01:56

2 Answers2

0

In Python // is the integer division operator, truncating the result. So it will always take the lowest closest integer since floating numbers are not exact if you treat them as integers, unless your numbers can be implicitly cast to integers.

0

Many decimal numbers can't be exactly expressed as floats, because floats are binary and not decimal. If you print those values to many decimal places you can see how far off they are and in which direction:

0.10000000000000000555
0.20000000000000001110
0.29999999999999998890
0.40000000000000002220
0.50000000000000000000
0.59999999999999997780
0.69999999999999995559
0.80000000000000004441
0.90000000000000002220

If the actual number is a little higher than the decimal representation, the division is going to be a smidge low, and flooring will take it down by 1.

See here for a description of the problem: https://docs.python.org/2/tutorial/floatingpoint.html

P.S. All integers up to 2**53 can be exactly represented as a float, so the 2.0 really is 2.0 and 1.0 really is 1.0.

I presume you've figured out by now that // is a floor division. float1 // float2 is the same as floor(float1 / float2).

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622