<jupyter_start><jupyter_text>Floats: Internal Representations- is Python's default implementation for representing real numbers- implemented using the C double type, also called binary64- uses a fixed number of bytes, 8 bytes but with overhead is 24 bytes- infinite numbers have an approximate float representation64 bits structure:- sign: 1 bit- exponent: 11 bits, range: -1022, 1023- significant digits: 52 bits, 15-17 significant (base 10) digits Examples:| Value | Sign | Exponent | Significant || --- | --- | --- | --- || 1.2345 | 0 | -4 | 12345 || 1234.5 | 0 | -1 | 12345 || 12345000000 | 0 | 6 | 12345 || 0.00012345 | 0 | -3 | 12345 || 12345e-50 | 0 | -50 | 12345 |Representation: decimal- numbers can be represented as base-10 intgers and fractionsExamples:0.75 = 7/10 + 5/100 = 7 x 10^-1 + 5 x 10^-20.256 = 2/10 + 5/100 + 6/1000 = 2 x 10^-1 + 5 x 10^-2 + 6 x 10^-3Representation: decimal- numbers are represented using bits, powers of 2- not all numbers have a finite binary representationExamples:binary float(0.11) = 1/2 + 1/4 = 1 x 2^-1 + 1 x 2^-2 (BASE 10)  Code examples<jupyter_code>float(10)
float(10.4)
float("12.5")<jupyter_output><empty_output><jupyter_text>Float from a string fraction raises a ValueError exception<jupyter_code>float("1/7")
from fractions import Fraction
a = Fraction("22/7")
float(a)<jupyter_output><empty_output><jupyter_text>Python will sometimes use smaller precision but internally the float has adifferent precision<jupyter_code>print(0.1)
format(0.1, ".15f")
format(0.1, ".25f")<jupyter_output><empty_output><jupyter_text>There are some float numbers that have an exact float representation<jupyter_code>print(0.125)
1/8
format(0.125, ".25f")<jupyter_output><empty_output><jupyter_text>Floats: Equality Testing- float equality can lead to some "weirdness", 0.1 + 0.1 + 0.1 != 0.3- equality can be compared with absolute tolerances, format(f, tolarance) Example of absolute tolerancesx = 0.1 + 0.1 + 0.1 --> 0.30000000000000004441y = 0.3 --> 0.2 --> 0.29999999999999998890difference: 0.00000000000000005551Using absolute tolerances, abs_tol = 10^-15 = 0.000000000000001math.fabs(x - y) < abs_tol   <-- Truea = 10000.1 + 10000.1 + 10000.1 --> 30000.30000000000291038305b = 30000.3 --> 30000.29999999999927240424difference: 0.0000000000033797881math.fabs(a - b) < abs_tol   <-- False  Examples of relative tolerances small numbersrel_tol = 0.001% = 1e-5tol = rel_tol * max(|x|, |y|)x = 0.1 + 0.1 + 0.1y = 0.3 --> 0.2tol = 0.000003000000000math.fabs(x - y) < tol   <-- True Big numbersx = 10000.1 + 10000.1 + 10000.1y = 30000.3tol = 0.300003000000000math.fabs(a - b) < tol   <-- True  Combining both techniques- use the larger of the two tolerances- math uses this solution as described in PEP 485- math.isclose(a, b, *, rel_tol-le-09, abs_tol=0.0)- math.isclose defaults is not good for values close to 0  Code Examples<jupyter_code>x = 0.1
format(x, ".25f")
x = 0.125
format(x, ".25f")
x = 0.125 + 0.125 + 0.125
y = 0.375
x == y
x = 0.1 + 0.1 + 0.1
y = 0.3
x == y
format(x, ".25f")
format(y, ".25f")
round(x, 3) == round(y, 3)
x = 10000.01
y = 10000.02
x/y
x = 0.1
y = 0.2
x/y
from math import isclose
x = 0.1+ 0.1 + 0.1
y = 0.3
isclose(x, y)
x == y
x = 123456789.01
y = 123456789.02
isclose(x, y, rel_tol=0.01)
x = 0.01
y = 0.02
isclose(x, y, rel_tol=0.01)
x = 0.0000001
y = 0.0000002
isclose(x, y, rel_tol=0.01)
isclose(x, y, rel_tol=0.01, abs_tol=0.01)<jupyter_output><empty_output><jupyter_text>Floats: Coercing to Integers- float -> Integer- data loss- different ways to configure data lossMethods (data loss in all cases)- truncation- floor- ceiling- rounding Truncation- returns the integer portion of the number- ignores everything after the decimal point- math.trunc()- ex: 10.4 -> 10- the int constructor uses truncation, ex: int(10.4) -> 10 Floor- returns the largest integer less than (or equal to) the number- ex: 10.4 -> 10, -10.4 -> -11- positive numbers, truncation and floor are equivalent- negative numbers, truncation and floor are different- //- math.floor() Ceiling- returns the smallest integer greater than (or equal to) the number- ex: 10.4 -> 11, -10.3 -> -10- math.ceil()  Code Examples<jupyter_code>from math import trunc
trunc(10.3), trunc(10.5), trunc(10.9)
int(10.4), int(10.5), int(10.9)
from math import floor
floor(10.3), floor(10.5), floor(10.9)
trunc(-10.3), trunc(-10.5), trunc(-10.9)
floor(-10.3), floor(-10.5), floor(-10.9)
from math import ceil
ceil(10.4), ceil(10.5), ceil(10.9)
ceil(-10.4), ceil(-10.5), ceil(-10.9)<jupyter_output><empty_output><jupyter_text>Floats: Rounding- built-in function, round(x, n=0)- returns integer x to the closest multiple of 10 ^-n- by default, n = 0, round will return the int- passing an n argument, the return type is the same as the passed type- it looks at the differences between the passed value and the integer before and after in the 10^-n position.- the integer with smallest difference is returned value- ex: round(18.2, -1) -> 20.0- with ties, same difference, it rounds using banker's rounding- banker's rounding: it rounds to the nearest value with an even least significant digit- ex: round(1.25, 1) -> 1.2, round(-1.25, 1) -> -1.2  <-- Not 1.3, -1.3 Rounding away from zero- sign(x) * int(x + 0.5 * sign(x))- ex: 10.4 + 0.5 = 10.9 = int(10.9) = 10- ex: 10.5 + 0.5 = 11.0 = int(11.0) = 11 Math.copysign()- returns the magnitude (absolute value) of x but with the sign of y- copysign(x, y)  Code Examples<jupyter_code>a = round(1.9)
a, type(a)
a = round(1.9, 0)
a, type(a)<jupyter_output><empty_output><jupyter_text>n > 0<jupyter_code>round(1.8888, 3), round(1.8888, 2), round(1.8888, 1), round(1.8888, 0)<jupyter_output><empty_output><jupyter_text>n < 0<jupyter_code>round(888.88, 1), round(888.88, 0), \
round(888.88, -1), round(888.88, -2), round(888.88, -3), round(888.88, -4)<jupyter_output><empty_output><jupyter_text>Ties - Banker's Rounding<jupyter_code>round(1.25, 1)
round(1.35, 1)
round(-1.25, 1)
round(-1.35, 1)<jupyter_output><empty_output><jupyter_text>Impementing a float rounding away from 0<jupyter_code>from math import copysign

def _round(x):
    return int(x + 0.5 * copysign(1, x))
round(1.5), _round(1.5)
round(2.5), _round(2.5)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14895330112721417, 'fraction_numerical': 0.1357487922705314, 'mean_word_length': 4.137303556658395, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 9, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '602423', 'license': 'MIT', 'n_tokens_mistral': 2851, 'n_tokens_neox': 2281, 'n_words': 719, 'path': 'python-deepdive/deepdive1/section04/section_04_floats.ipynb', 'repo_name': 'erictapia/devstacklab', 'size': '6210'}