# Numbers

There’s nothing magical about numbers in Python, and we’ve already discovered how we perform operations on them.

```>>> (2 * (1 + 3) - 5) / 0.5
2
>>> 11 % 4
3
```

Integer division in Python 2

If for any reason (e.g. you want to use LHCb or Alice software) you have to use Python 2, beware of that Python 2 has a few different types of numbers, and they can behave differently.

```>>> 10/3
3
>>> 10.0/3.0
3.3333333333333335
```

Interesting. Something different happens when we use numbers with and without decimal places! This occurs because numbers given with decimal places, like `3.14` are floats, while those without, like `3`, are integers.

For historical reasons, dividing two integers in Python 2 returns an integer, where the intermediate result is always rounded down. Division using at least one float gives us the more intuitive answer.

In Python 3, division with integers works the same way as with floats. You can ask to have this behaviour in Python 2.

```>>> from __future__ import division
>>> 3 / 4
0.75
>>> 3.0 / 4.0
0.75
```

Because the default behaviour in Python 2 is quite unintuitive, we recommend using the `from __future__ import division` line everywhere. We’ll come to what exactly this line is doing shortly.

If you do want a rounding division, you then can ask for it explicitly with round, or, if you want an integer division (truncating, rounding towards 0):

```>>> 5 / 3
1.66666666667

>>> round(5 / 3)
2

>>> 5 // 3
1
```

Operators

This behaviour can be explained in terms of operators and the double-underscore methods. You can see that numbers have two methods for division:

```>>> dir(1)
[...,
'__floordiv__',
...
'__truediv__',
...]
```

In Python 2, the `/` operator corresponded to the `__floordiv__` method when used with integers, but the `__truediv__` operator when used with floats. In Python 3, and when using the `from __future__ import division` line, the `/` operator always uses the `__truediv__` method.

Python also lets you manipulate complex numbers, using `j` to represent the complex term.

```>>> a = 1 + 4j
>>> b = 4 - 1j
>>> a - b
(-3+5j)
```

Complex numbers are objects, of course, and have some useful functions and properties attached to them.

```>>> a.conjugate()
(1-4j)
>>> a.imag
4.0
>>> a.real
1.0
```

Somewhat confusingly, computing the magnitude of a complex number can be done with the `abs` method, which is available globally.

```>>> abs(a)
4.123105625617661
>>> import numpy as np
>>> np.sqrt(a.real**2 + a.imag**2)
4.123105625617661
```

This also demonstrates the `**` operator, which for real numbers corresponds to exponentiation.

Each type of number can be created literally, like we’ve been doing, by just typing the number into your shell or source code, and by using the correspond methods.

```>>> int()
0
>>> float()
0.0
>>> complex()
0j
```