===============
Python: Numbers
===============
There are four distinct numeric types:
- ``int``: integers. (Limited precision.)
- ``long``: long integers. (Unlimited precision.) They behave exactly like
plain ``int``'s, but they can assume arbitrary values.
- ``float``: floating point numbers. Also called floats, they represent real numbers. They are written with a decimal point dividing the integer and fractional parts. Floats may also be in scientific notation, with E or e indicating the power of 10.
- ``bool``: Boolean conditions. They can assume only two values: ``True`` and ``False``.
They are used to represent the result of comparisons.
**Example**. Let's create four variables, one for each type, and print them on the screen with ``print``::
x = 10
y = 10L
z = 3.14
c = False
# Print the four variables
print x, y, z, c
# The same, adding some text
print "x =", x, "y =", y, "z =", z, "; the condition is", c
This syntax of ``print`` is valid for all variable types, not only numeric types.
Operations
----------
All numeric types support default **arithmetic** operations:
- sum ``+``, difference ``-``, product ``*``
- division ``/``, integer division ``//``, remainder ``%``.
- power ``**``.
The type of the result of ``n operation m`` is the most "complex" type between the type of
``n`` and ``m``. The complexity hierarchy is::
bool < int < long < float
**Example**. Two examples of automatic conversion::
result = 1 * 1L # int * long
print result
print type(result) # long
result = 1.0 + 1L # float * long
print result
print type(result) # float
.. warning::
To avoid errors, you should choose the most appropriate type for your variables, so that the *type* of the result is sufficiently "complex" to represent the *value* of the result!
See for example the following GC-content exercise.
All numeric types support **comparison** operations:
- equal ``==`` not equal ``!=`` (or ``<>``)
- strictly less than ``<`` strictly greater than ``>``
- less than or equal``<=`` greater than or equal ``>=``
The expression has value ``True`` if the condition is satisfied, otherwise ``False``.
The result of a comparison is always ``bool``.
**Example**. Let's consider::
na, nc, ng, nt = 2, 6, 50, 4
result = (na + nt) > (nc + ng)
print result
print type(result)
We can build complex conditions using Boolean operations:
- ``a and b`` is ``True`` if both ``a`` and ``b`` are ``True``.
- ``a or b`` is ``True`` if at least one between ``a`` and ``b`` is ``True``.
- ``not a`` is ``True`` only if ``a`` is ``False``.
.. warning::
In this context, both ``a`` and ``b`` should be ``bool``, otherwise the result may seem apparently bizarre.
**Example**. ``x > 12`` and ``x < 34`` both result ``bool``, so we can combine them to obtain::
# int int
# | |
print (x > 12) and (x < 34)
# \______/ \______/
# bool bool
# \___________________/
# bool
or::
# int int
# | |
print (not (x > 12)) or (x < 34)
# \______/
# bool
# \____________/ \______/
# bool bool
# \________________________/
# bool
Examples
--------
**Example**. Let's calculate the zeros of the quadratic equation :math:`x^2 - 1 = 0`::
a, b, c = 1.0, 0.0, -1.0
delta = b**2 - 4*a*c
zero1 = (-b + delta**0.5) / (2 * a)
zero2 = (-b - delta**0.5) / (2 * a)
print zero1, zero2
Here we use ``x**0.5`` to calculate the square root: :math:`\sqrt{x} = x^\frac{1}{2}`.
**Example**. We want to calculate the `GC-content `_
of a genomic region. We know that the region:
- Is 1521 nucleotides long.
- Contains 316 cytosines.
- Contains 235 guanines.
The GC-content is defined as :math:`(g + c) / n`.
To calculate the result, we may write::
n, c, g = 1521, 316, 235
gc_content = (c + g) / n
print gc_content
unfortunately, the result of this code is ``0``! Why?
The problem is that the resulting proportion, amounting to approximately ``0.362``, cannot be expressed by an integer: we need a rational number. Since both ``n`` and ``m``
are integers, also ``gc_content = n / m`` will be an integer::
print type(gc_content)
As a consequence, ``0.362`` is approximated to the nearest integer: ``0``.
*Oops*!
To solve this problem, ``gc_content`` needs to be a ``float``. We can do it in two ways:
- Modifying the type of ``n``, ``m`` or ``g``::
n, c, g = 1521.0, 316.0, 235.0
gc_content = (c + g) / n
print gc_content
- Using an explicit conversion to a ``float``::
n, c, g = 1521, 316, 235
gc_content = float(c + g) / float(n)
print gc_content
**Example**. To check that ``x`` falls in the interval A :math:`= [10,50]`
let's write::
x = 17
min_a, max_a = 10, 50
inside_a = (min_a <= x <= max_a)
print inside_a
or::
inside_a = ((x >= min_a) and (x <= max_a))
Assuming that ``inside_a``, ``inside_b`` and ``inside_c`` indicate that ``x`` is contained
in interval A, B or C, respectively, we can create more complex conditions::
# x is in at least one interval
inside_at_least_one = inside_a or inside_b or inside_c
# x is in both A and B, but not in C
inside_a_and_b_but_not_c = inside_a and inside_b and (not inside_c)
Exercises
---------
#. Create the following variables, checking that value and type are correct (using ``print`` and ``type``):
#. ``a`` and ``b`` with values ``12`` and ``23`` as integers.
#. ``c`` and ``d`` with values ``34`` and ``45`` as long integers.
#. ``x`` and ``y`` with values ``21`` and ``14`` as floats.
#. Using ``print`` (once), print:
#. All the above variables in the same line.
#. All the above variables, separated by ``;``, on the same line.
#. The text "the product of ``a`` and ``b`` is ``a * b``", replacing
``a``, ``b`` and ``a * b`` with the variable values.
#. Find the value and the type of:
#. The product of ``a`` and ``b``.
#. The difference between ``c`` and ``d``.
#. The division of ``x`` by ``y``.
#. The integer division of ``a`` by ``b``.
#. The integer division of ``c`` by ``d``.
#. The integer division of ``x`` by ``y``.
#. The product of ``a`` and ``c``.
#. The product of ``b`` and ``y``.
#. The product of ``x`` and ``d``.
#. ``2`` to the power ``0``.
#. ``2`` to the power ``100``.
#. ``2`` to the power ``1.2``.
#. ``2`` to the power ``-2``.
#. The square root of ``4``.
#. The square root of ``2``.
#. What is the difference between:
#. ``10 / 12``
#. ``10 / 12.0``
#. ``10 // 12``
#. ``10 // 12.0``
#. What is the difference between:
#. ``10 % 3``
#. ``10 % 3.0``
#. Using ``pi = 3.141592`` and given ``r = 2.5``, calculate:
#. The circumference of a circle with radius ``r``: :math:`2 \pi r`.
#. The area of a circle with radius ``r``: :math:`\pi r^2`.
#. The volume of a sphere with radius ``r``: :math:`\frac{4}{3} \pi r^3`.
#. Create 2 variables ``a = 100`` and ``b = True``. Using an adequate number of auxiliary variables (with arbitrary names!), give the value of ``a`` to ``b`` and viceversa.
(Writing ``a = True`` and ``b = 100`` is not sufficient!)
Can it be done with only one auxiliary variable?
#. On the same strand of DNA there are 2 genes. The first includes i
nucelotides from position 10 to position 20, the second nucleotides from
position 30 to position 40. Let's write this::
gene1_start, gene1_end = 10, 20
gene2_start, gene2_end = 30, 40
Given a variable ``pos`` representing an arbitrary position on the DNA strand, write some comparisons to verify if:
#. ``pos`` is in the first gene.
#. ``pos`` is in the second gene.
#. ``pos`` is between the start of the first gene and the end of the second.
#. ``pos`` is between the start of the first gene and the end of the second, but not in any of the genes.
#. ``pos`` is before the start of the first gene or after the end of the second.
#. ``pos`` is inside one of the genes.
#. ``pos`` is distant no more than 10 nucleotides from the beginning of the first gene.
#. Given three Boolean variables ``t``, ``u``, and ``v``, write expressions that are ``True`` if and only if:
#. ``t``, ``u``, ``v`` are all true.
#. ``t`` is true or ``u`` is true, but not both.
#. Exactly one of the three variables is false.
#. Exactly one of the three variables is true.
#. Exercise 1.4 from [book2]_: Exponential Growth
Given optimal growth conditions, a single E. coli bacterium can divide
within 20 minutes. If the conditions stay optimal, how many bacteria are
there after 8 hours?