<jupyter_start><jupyter_text>Python basics 3 - floats [Download exercises zip](../_static/generated/basics.zip)[Browse online files](https://github.com/DavidLeoni/softpython-en/tree/master/basics)**PREREQUISITES:**    * **Having read** [basics 1 - integers](https://en.softpython.org/basics/basics1-ints-sol.html)* **Having read** [basics 2 - booleans](https://en.softpython.org/basics/basics2-bools-sol.html)          Real numbersPython saves the real numbers (floating point numbers) in 64 bit of information divided by sign, exponent and mantissa (also called significand). Let's see an example:<jupyter_code>3.14
type(3.14)<jupyter_output><empty_output><jupyter_text>**WARNING: you must use the dot instead of comma!**        So you will write `3.14` instead of `3,14`        Be very careful, whenever you copy numbers from documents in latin languages, they might contain very  insidious commas!      Scientifical notationWhenever numbers are very big or very small, to avoid having to write too many zeros it is convenient to use scientifical notation with the _e_ like $xen$ which multiplies  the number _x_ by $10^n$With this notation, in memory are only put the most significative digits ( the _mantissa_ ) and the exponent, thus avoiding to waste space.<jupyter_code>75e1
75e2
75e3
75e123
75e0
75e-1
75e-2
75e-123<jupyter_output><empty_output><jupyter_text>**QUESTION**: Look at the following expressions, and try to find which result they produce (or if they give and error):    1.  ```python    print(1.000.000)    ```1.  ```    print(3,000,000.000)    ```1.  ```python    print(2000000.000)    ```1.  ```python    print(2000000.0)    ```1.  ```python    print(0.000.123)    ```    1.  ```python    print(0.123)    ```        1.  ```python    print(0.-123)    ```            1.  ```python    print(3e0)    ```1.  ```python    print(3.0e0)    ```1.  ```python    print(7e-1)    ``` 1.  ```python    print(3.0e2)    ```1.  ```python    print(3.0e-2)    ```    1.  ```python    print(3.0-e2)    ```1.  ```python    print(4e2-4e1)    ```  Too big or too small numbers Sometimes calculations on very big or extra small numbers  may give as a result `math.nan` (Not a Number) or `math.inf`. For the moment we just mention them, you can find a detailed description in the [Numpy page](https://en.softpython.org/matrices-numpy/matrices-numpy-sol.htmlNaN-e-infinities)  Exercise - circle✪ Calculate the area of a circle at the center of a soccer ball (radius = 9.1m), remember that  $area=pi*r^2$Your code should print as result `263.02199094102605`<jupyter_code># SOLUTION

r = 9.15
pi = 3.1415926536
area = pi*(r**2)
print(area)<jupyter_output>263.02199094102605<jupyter_text>Note that the parenthesis around the squared `r` are not necessary because the power operator has the precedence, but they may help in augmenting the code readability.We recall here the operator precedence: |Operator|Description||---------|-----------||`**`|Power (maximum precedence)||`+` `-`| unary plus and minus||`*` `/` `//` `%`|Multiplication, division, integer division, modulo||`+` `-`| Addition and subtraction||`` `>=`| comparison operators||`==` `!=` | equality operators||`not` `or` `and`|Logical operators (minimum precedence)|  Exercise - fractioning✪ Write some code to calculate the value of the following formula for  `x = 0.000003`, you should obtain `2.753278226511882` $$\Large -\frac{\sqrt{x+3}}{\frac{(x + 2)^3}{\log{x}}}$$<jupyter_code>x = 0.000003

# write here
import math
- math.sqrt(x+3) / (((x+2)**3)/math.log(x))<jupyter_output><empty_output><jupyter_text>Exercise - summationWrite some code to calculate the value of the following expression (don't use cycles, write down all calculations), you should obtain `20.53333333333333` $$\normalsize \sum_{j=1}^{3}{\frac{j^4}{j + 2}}$$<jupyter_code># write here
((1**4) / (1+2)) + ((2**4) / (2+2)) + ((3**4) / (3+2))<jupyter_output><empty_output><jupyter_text>Reals - conversionIf we want to convert a real to an integer, several ways are available:|Function|Description|Mathematical symbol|Result||--------|-----------|------------------|---------||`math.floor(x)`| round x to inferior integer|$$\lfloor{8.7}\rfloor$$|8||`int(x)`| round x to inferior integer|$$\lfloor{8.7}\rfloor$$|8||`math.ceil(x)`| round x to superior integer|$$\lceil{5.3}\rceil$$|6||`round(x)`| round x to closest integer|$$\lfloor{2.49}\rceil$$|2||          | |$$\lfloor{2.51}\rceil$$|3| **QUESTION**: Look at the following expressions, and for each of them try to guess which result it produces (or if it gives an error).1.  ```python    math.floor(2.3)    ```1.  ```python    math.floor(-2.3)    ```1.  ```python    round(3.49)    ```1.  ```python    round(3.51)    ```    1.  ```python    round(-3.49)    ```    1.  ```python    round(-3.51)    ```1.  ```python    math.ceil(8.1)    ```1.  ```python    math.ceil(-8.1)    ```     **QUESTION**: Given a float `x`, the following formula is:        ```pythonmath.floor(math.ceil(x)) == math.ceil(math.floor(x))```1. always `True`2. always  `False`3. sometimes `True` and sometimes `False` (give examples) **ANSWER**: 3: for integers like `x=2.0` it is `True`, in other cases like `x=2.3` it is `False` **QUESTION**: Given a float `x`, the following formula is:        ```pythonmath.floor(x) == -math.ceil(-x)```1. always `True`2. always `False`3. sometimes `True` and sometimes `False` (give examples) **ANSWER**:  1.  Exercise -  Invigorate✪ Excessive studies lead you search on internet recipes of energetic drinks. Luckily, a guru of nutrition just posted on her Instagram channel @HealthyDrink this recipe of a miracle drink:> Pour in a mixer 2 decilitres of kiwi juice, 4 decilitres of soy sauce, and 3 decilitres of shampoo of karitè bio. Mix vigorously and then pour half drink into a glass. Fill the glass until the superior deciliter. Swallow in one shot.You run shopping the ingredients, and get ready for mixing them. You have a measuring cup with which you transfer the precious fluids, one by one. While transfering, you always pour a little bit more than necessary (but never more than 1 decilitre), and for each ingredient you then remove the excess.* **DO NOT** use subtractions, try using only rounding operators Example - given:```pythonkiwi = 2.4soia = 4.8shampoo = 3.1measuring_cup = 0.0mixer = 0glass = 0.0```Your code must print:```I pour into the measuring cup 2.4 dl of kiwi juice, then I remove excess until keeping 2 dlI transfer into the mixer, now it contains 2.0 dlI pour into the measuring cup 4.8 dl of soia, then I remove excess until keeping 4 dlI transfer into the mixer, now it contains 6.0 dlI pour into the measuring cup 3.1 dl of shampoo, then I remove excess until keeping 3 dlI transfer into the mixer, now it contains 9.0 dlI pour half of the mix ( 4.5 dl ) into the glassI fill the glass until superior deciliter, now it contains: 5 dl```<jupyter_code>import math 

kiwi = 2.4
soy = 4.8
shampoo = 3.1
measuring_cup = 0.0
mixer = 0.0
glass = 0.0


# write here
print('I pour into the measuring cup', kiwi, 'dl of kiwi juice, then I remove excess until keeping', int(kiwi), 'dl')
mixer += int(kiwi)
print('I transfer into the mixer, now it contains', mixer, 'dl')
print('I pour into the measuring cup', soy, 'dl of soia, then I remove excess until keeping', int(soy), 'dl')
mixer += int(soy)
print('I transfer into the mixer, now it contains', mixer, 'dl')
print('I pour into the measuring cup', shampoo, 'dl of shampoo, then I remove excess until keeping', int(shampoo), 'dl') 
mixer += int(shampoo)
print('I transfer into the mixer, now it contains', mixer, 'dl')
glass = mixer/2
print('I pour half of the mix (', glass, 'dl ) into the glass')
print('I fill the glass until superior deciliter, now it contains:', math.ceil(glass), 'dl')<jupyter_output>I pour into the measuring cup 2.4 dl of kiwi juice, then I remove excess until keeping 2 dl
I transfer into the mixer, now it contains 2.0 dl
I pour into the measuring cup 4.8 dl of soia, then I remove excess until keeping 4 dl
I transfer into the mixer, now it contains 6.0 dl
I pour into the measuring cup 3.1 dl of shampoo, then I remove excess until keeping 3 dl
I transfer into the mixer, now it contains 9.0 dl
I pour half of the mix ( 4.5 dl ) into the glass
I fill the glass until superior deciliter, now it contains: 5 dl<jupyter_text>Exercise - roundminder✪ Write some code to calculate the value of the following formula for `x = -5.51`, you should obtain `41`$$\large \lvert{\lceil{x}\rceil}\rvert + \lfloor{x}\rceil^2$$<jupyter_code>import math 

x = -5.51   # 41
#x = -5.49  # 30

# write here
abs(math.ceil(x)) + round(x)**2<jupyter_output><empty_output><jupyter_text>Reals - equality    **WARNING: what follows is valid for** ***all*** **programming languages!**     Some results will look weird but this is the way most processors (CPU) operates, independently from Python.        When floating point calculations are performed, the processor may introduce rounding errors due to limits of internal representation. Under the hood the numbers like floats are memorized in a sequence of binary code of 64 bits, according to _IEEE-754 floating point arithmetic_ standard: this imposes a physical limit to the precision of numbers, and sometimes we ight get surprises due to conversion from decimal to binary. For example, let's try printing `4.1`:<jupyter_code>print(4.1)<jupyter_output>4.1<jupyter_text>For our convenience Python is showing us `4.1`, but in reality in the processor memory ended up a different number! Which one? To discover what it hides, with `format` function we can explicitly format the number to, for example 55 digits of precision by using the `f` format specifier:<jupyter_code>format(4.1, '.55f')<jupyter_output><empty_output><jupyter_text>We can then wonder what the result of this calculus might be:<jupyter_code>print(7.9 - 3.8)<jupyter_output>4.1000000000000005<jupyter_text>We note the result is still different from the expected one! By investigating further, we notice Python is not even showing all the digits:<jupyter_code>format(7.9 - 3.8, '.55f')<jupyter_output><empty_output><jupyter_text>What if wanted to know if the two calculations with float produce the 'same' result?**WARNING: AVOID** `==` **WITH FLOATS!**       To understand if the result between the two calculations with the floats is the same, **YOU CANNOT** use the `==` operator !<jupyter_code>7.9 - 3.8 == 4.1    # TROUBLE AHEAD!<jupyter_output><empty_output><jupyter_text>Instead, you should prefer alternative that evaluate if a float number is _close_ to anoter, like for example the handy function [math.isclose](https://docs.python.org/3/library/math.htmlmath.isclose):<jupyter_code>import math

math.isclose(7.9 - 3.8, 4.1)   # MUCH BETTER<jupyter_output><empty_output><jupyter_text>By default `math.isclose` uses a precision of `1e-09`, but, if needed, you can also pass a tolerance limit in which the difference of the numbers must be so to be considered equal:<jupyter_code>math.isclose(7.9 - 3.8, 4.1, abs_tol=0.000001)<jupyter_output><empty_output><jupyter_text>**QUESTION**: Can we perfectly represent the number $\sqrt{2}$ as a `float`? **ANSWER**: $\sqrt{2}$ is irrational so there's no hope of a perfect representation, any calculation will always have a certain degree of imprecision. **QUESTION**: Which of these expressions give the same result?```python    import mathprint('a)', math.sqrt(3)**2 == 3.0)print('b)', abs(math.sqrt(3)**2 - 3.0) < 0.0000001)print('c)', math.isclose(math.sqrt(3)**2, 3.0, abs_tol=0.0000001))``` **ANSWER**: b) and c) give `True`. a) gives `False`, because durting floating point calculations rounding errors are made.  Exercise - quadratic ✪ Write some code to calculate the zeroes of the equation $ax^2-b = 0$ - Show numbers with **20 digits** of precision- At the end check that by substituting the value obtained `x` into the equation you actually obtain zero. Example - given:```pythona = 11.0b = 3.3```after your code it must print:```11.0 * x**2 - 3.3 = 0  per x1 = 0.5477225575051660744211.0 * x**2 - 3.3 = 0  per x2 = -0.54772255750516607442Is 0.54772255750516607442 a solution? TrueIs -0.54772255750516607442 a solution? True```<jupyter_code>#jupman-purge-output
a = 11.0
b = 3.3  

# write here

import math

x1 = math.sqrt(b/a)
x2 = -math.sqrt(b/a)

print(a, "* x**2 -",b,"= 0  per x1 =", format(x1, '.20f'))
print(a, "* x**2 -",b,"= 0  per x2 =", format(x2, '.20f'))

# we need to change the default tolerance value
print("Is", format(x1, '.20f'), "a solution?", math.isclose(a*(x1**2) - b,0, abs_tol=0.00001))
print("Is", format(x2, '.20f'), "a solution?", math.isclose(a*((x2)**2) - b,0, abs_tol=0.00001))<jupyter_output>11.0 * x**2 - 3.3 = 0  per x1 = 0.54772255750516607442
11.0 * x**2 - 3.3 = 0  per x2 = -0.54772255750516607442
Is 0.54772255750516607442 a solution? True
Is -0.54772255750516607442 a solution? True<jupyter_text>Exercise - trendy✪✪ You are already thinking about next vacations, but there is a big problem: where do you go, if you don't have a _selfie-stick_? You cannot leave with this serious anxiety: to uniform yourself to this mass phenomena you must buy the stick which is most similar to others. You then conduct a rigourous statistical survey among turists obssessed by selfie sticks with the goal to find the most frequent brands of sticks, in other words, the _mode_ of the frequencies. You obtain these results:<jupyter_code>b1,b2,b3,b4,b5 = 'TooManyLikes', 'Boombasticks', 'Timewasters Inc', 'Vanity 3.0','TrashTrend' # brand
f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.3   # frequencies (as percentages)<jupyter_output><empty_output><jupyter_text>We deduce that masses love selfie-sticks of the brand `'Boombasticks'` and `TrashTrend`, both in a tie with 30% turists each. Write some code which prints this result:```TooManyLikes is the most frequent? False ( 25.0 % )Boombasticks is the most frequent? True ( 30.0 % )Timewasters Inc is the most frequent? False ( 10.0 % )Vanity 3.0 is the most frequent? False ( 5.0 % )TrashTrend is the most frequent? True ( 30.0 % )```* **WARNING**: your code must work with **ANY** series of variables !!<jupyter_code>#jupman-purge-output
b1,b2,b3,b4,b5 = 'TooManyLikes', 'Boombasticks', 'Timewasters Inc', 'Vanity 3.0','TrashTrend'    # brand

f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.3  # frequencies (as percentages)  False True False False True
# CAREFUL, they look the same but it must work also with these!
#f1,f2,f3,f4,f5 = 0.25, 0.3, 0.1, 0.05, 0.1 + 0.2  #  False True False False True
                                        
# write here
mx = max(f1,f2,f3,f4,f5)
print(b1, 'is the most frequent?', math.isclose(f1,mx), '(', format(f1*100.0, '.1f'),'% )')
print(b2, 'is the most frequent?', math.isclose(f2,mx), '(', format(f2*100.0, '.1f'),'% )')
print(b3, 'is the most frequent?', math.isclose(f3,mx), '(', format(f3*100.0, '.1f'),'% )')
print(b4, 'is the most frequent?', math.isclose(f4,mx), '(', format(f4*100.0, '.1f'),'% )')
print(b5, 'is the most frequent?', math.isclose(f5,mx), '(', format(f5*100.0, '.1f'),'% )')<jupyter_output>TooManyLikes is the most frequent? False ( 25.0 % )
Boombasticks is the most frequent? True ( 30.0 % )
Timewasters Inc is the most frequent? False ( 10.0 % )
Vanity 3.0 is the most frequent? False ( 5.0 % )
TrashTrend is the most frequent? True ( 30.0 % )<jupyter_text>Decimal numbersFor most applications float numbers are sufficient, if you are conscius of their limits of representation and equality.  If you really need more precision and/or preditability, Python offers a dedicated numeric type  called `Decimal`, which allows arbitrary precision. To use it, you must first import `decimal` library:<jupyter_code>from decimal import Decimal<jupyter_output><empty_output><jupyter_text>You can create a  `Decimal` from a string:<jupyter_code>Decimal('4.1')<jupyter_output><empty_output><jupyter_text>**WARNING: if you create a Decimal from a costant, use a string!**        If you pass a `float` you risk losing the utility of Decimals:<jupyter_code>Decimal(4.1)  # this way I keep the problems of floats ...<jupyter_output><empty_output><jupyter_text>Operations between `Decimal`s produce other `Decimal`s:<jupyter_code>Decimal('7.9') - Decimal('3.8')<jupyter_output><empty_output><jupyter_text>This time, we can freely use the equality operator and obtain the same result:<jupyter_code>Decimal('4.1') == Decimal('7.9') - Decimal('3.8')<jupyter_output><empty_output><jupyter_text>Some mathematical functions are also supported, and often they behave more predictably (note we are **not** using `math.sqrt`):<jupyter_code>Decimal('2').sqrt()<jupyter_output><empty_output><jupyter_text>**Remember: computer memory is still finite!**Decimals can't be solve all problems in the universe: for example,$\sqrt{2}$ will never fit the memory of any computer! We can verify the limitations by squaring it:<jupyter_code>Decimal('2').sqrt()**Decimal('2')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13461992445703494, 'fraction_numerical': 0.053824362606232294, 'mean_word_length': 4.523142112125163, 'pattern_counts': {'":': 0, '<': 92, '<?xml version=': 0, '>': 93, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '24', 'dir': 'jupyter-structured-clean-dedup', 'id': '465251', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 6066, 'n_tokens_neox': 5499, 'n_words': 2024, 'path': 'basics/basics3-floats-sol.ipynb', 'repo_name': 'simoneb1x/softpython-en', 'size': '16944'}