138

I was trying to normalize a set of numbers from -100 to 0 to a range of 10-100 and was having problems only to notice that even with no variables at all, this does not evaluate the way I would expect it to:

>>> (20-10) / (100-10)
0

Float division doesn't work either:

>>> float((20-10) / (100-10))
0.0

If either side of the division is cast to a float it will work:

>>> (20-10) / float((100-10))
0.1111111111111111

Each side in the first example is evaluating as an int which means the final answer will be cast to an int. Since 0.111 is less than .5, it rounds to 0. It is not transparent in my opinion, but I guess that's the way it is.

What is the explanation?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Adam Nelson
  • 7,932
  • 11
  • 44
  • 64
  • 1
    See also: [Why doesn’t this division work in python?](http://stackoverflow.com/questions/1787249/why-doesnt-this-division-work-in-python/1787255#1787255) – miku Jun 02 '10 at 14:36
  • 3
    Adam, I still don't like your explanation. The first example is integer division, which simply returns 0. The second example is parenthesized wrongly for the effect you want. – President James K. Polk Jun 02 '10 at 23:26
  • @GregS The first example was the problem. The second example is explanatory and was written after the first question. All the answers below explain the issue very well, especially @KennyTM 's. It's important to note that my original problem is only an issue on Python 2.x, not 3. It's a little disconcerting that the behavior will change like that but now that I know, I'll use from __future__ import division and use the 3.x behavior. Cheers. – Adam Nelson Jun 03 '10 at 13:57
  • 1
    Adam, please correct your last EDIT. The right side has nothing special to it; in order for a division to be float, either the numerator or the denominator (or both) needs to be float. If you think you read in the docs that the right hand side needs to be float, then either the documentation is badly phrased and should be corrected, or you misunderstood it. Did you see an example, perhaps, and then extrapolate a rule out of it? – tzot Jun 27 '10 at 22:24
  • "Float division doesn't work either:" This example **isn't** "float division", which is the problem. `float` is being **called** here, and whenever something is called, the arguments are evalutated **before** the call. `float` only sees an integer, and cannot deduce anything about the calculation that produced the integer. – Karl Knechtel Jun 11 '22 at 17:59
  • I closed this as a duplicate because answers (including the accepted answer) don't address the reasoning behind the design decision in Python 2.x (it would probably be off-topic anyway, due to being Primarily Opinion-Based). The linked duplicate is the canonical explaining how to write the code in order to get a floating-point result, which seems to be all OP wanted (despite that OP already had a working solution). – Karl Knechtel Oct 13 '22 at 18:11

13 Answers13

247

You're using Python 2.x, where integer divisions will truncate instead of becoming a floating point number.

>>> 1 / 2
0

You should make one of them a float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

or from __future__ import division, which the forces / to adopt Python 3.x's behavior that always returns a float.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 10
    If you use `from __future__ import division` you can get the old C-style division behavior by using two slashes (e.g. `1 // 2` will result in 0). See [Pep 238 Changing the Division Operator](http://www.python.org/dev/peps/pep-0238/) – User Nov 28 '13 at 05:40
  • 1
    @User No need for the import from `__future__`. In both Python 2 and 3 `//` refers to `__floordiv__()` by default. – Janosh Oct 27 '18 at 16:29
  • @Casimir They're saying, if you need floor division, it's available. You're not stuck with the `__future__.division` behaviour. – wjandrea Jan 19 '22 at 20:38
21

You're putting Integers in so Python is giving you an integer back:

>>> 10 / 90
0

If if you cast this to a float afterwards the rounding will have already been done, in other words, 0 integer will always become 0 float.

If you use floats on either side of the division then Python will give you the answer you expect.

>>> 10 / 90.0
0.1111111111111111

So in your case:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111
David Webb
  • 190,537
  • 57
  • 313
  • 299
13

In Python 2.7, the / operator is an integer division if inputs are integers:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

In Python 3.3, the / operator is a float division even if the inputs are integer.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

For integer division in Python 3, we will use the // operator.

The // operator is an integer division operator in both Python 2.7 and Python 3.3.

In Python 2.7 and Python 3.3:

>>>20//15
1

Now, see the comparison

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

For the above program, the output will be False in Python 2.7 and True in Python 3.3.

In Python 2.7 a = 1.75 and b = 1.

In Python 3.3 a = 1.75 and b = 1.75, just because / is a float division.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hackwithharsha
  • 901
  • 1
  • 16
  • 39
11

You need to change it to a float BEFORE you do the division. That is:

float(20 - 10) / (100 - 10)
A. Levy
  • 29,056
  • 6
  • 39
  • 56
8

It has to do with the version of python that you use. Basically it adopts the C behavior: if you divide two integers, the results will be rounded down to an integer. Also keep in mind that Python does the operations from left to right, which plays a role when you typecast.

Example: Since this is a question that always pops in my head when I am doing arithmetic operations (should I convert to float and which number), an example from that aspect is presented:

>>> a = 1/2/3/4/5/4/3
>>> a
0

When we divide integers, not surprisingly it gets lower rounded.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

If we typecast the last integer to float, we will still get zero, since by the time our number gets divided by the float has already become 0 because of the integer division.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

Same scenario as above but shifting the float typecast a little closer to the left side.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

Finally, when we typecast the first integer to float, the result is the desired one, since beginning from the first division, i.e. the leftmost one, we use floats.

Extra 1: If you are trying to answer that to improve arithmetic evaluation, you should check this

Extra 2: Please be careful of the following scenario:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0
Community
  • 1
  • 1
George
  • 774
  • 2
  • 9
  • 18
4

Specifying a float by placing a '.' after the number will also cause it to default to float.

>>> 1 / 2
0

>>> 1. / 2.
0.5
billmanH
  • 1,298
  • 1
  • 14
  • 25
2

Make at least one of them float, then it will be float division, not integer:

>>> (20.0-10) / (100-10)
0.1111111111111111

Casting the result to float is too late.

unbeli
  • 29,501
  • 5
  • 55
  • 57
1

In python cv2 not updated the division calculation. so, you must include from __future__ import division in first line of the program.

Jérôme Pin
  • 1,363
  • 4
  • 18
  • 33
0

Either way, it's integer division. 10/90 = 0. In the second case, you're merely casting 0 to a float.

Try casting one of the operands of "/" to be a float:

float(20-10) / (100-10)
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
0

You're casting to float after the division has already happened in your second example. Try this:

float(20-10) / float(100-10)
David M
  • 71,481
  • 13
  • 158
  • 186
0

I'm somewhat surprised that no one has mentioned that the original poster might have liked rational numbers to result. Should you be interested in this, the Python-based program Sage has your back. (Currently still based on Python 2.x, though 3.x is under way.)

sage: (20-10) / (100-10)
1/9

This isn't a solution for everyone, because it does do some preparsing so these numbers aren't ints, but Sage Integer class elements. Still, worth mentioning as a part of the Python ecosystem.

kcrisman
  • 4,374
  • 20
  • 41
0

Personally I preferred to insert a 1. * at the very beginning. So the expression become something like this:

1. * (20-10) / (100-10)

As I always do a division for some formula like:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

so it is impossible to simply add a .0 like 20.0. And in my case, wrapping with a float() may lose a little bit readability.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
FredWe
  • 11
  • 4
0

In Python 3, the “//” operator works as a floor division for integer and float arguments. However, the operator / returns a float value if one of the arguments is a float (this is similar to C++)

eg:

# A Python program to demonstrate the use of
# "//" for integers
print (5//2)
print (-5//2)

Output:

2
-3



# A Python program to demonstrate use of
# "/" for floating point numbers
print (5.0/2)
print (-5.0/2)

Output:

2.5
-2.5

ref: https://www.geeksforgeeks.org/division-operator-in-python/

Zgpeace
  • 3,927
  • 33
  • 31