<jupyter_start><jupyter_text>https://stackoverflow.com/questions/5595425/what-is-the-best-way-to-compare-floats-for-almost-equality-in-python Like integers you can compare floating point numbers if they are exactly the same<jupyter_code>a = 1
b = 1
a == b
a = .1
b = .10
a == b

7/3*3, 7*3/3, 7/3*3 == 7*3/3<jupyter_output><empty_output><jupyter_text>PEP 485 -- A Function for testing approximate equality https://www.python.org/dev/peps/pep-0485/> Floating point values contain limited precision, which results intheir being unable to exactly represent some values, and for errors toaccumulate with repeated computation.  Floating Point Arithmetic: Issues and Limitations : https://docs.python.org/3/tutorial/floatingpoint.html> Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine.> Many users are not aware of the approximation because of the way values are displayed. [Python only prints a decimal approximation to the true decimal value of the binary approximation stored by the machine. On most machines](https://), if Python were to print the true decimal value of the binary approximation stored for 0.1, it would have to display```>>> 0.10.1000000000000000055511151231257827021181583404541015625```> That is more digits than most people find useful, so Python keeps the number of digits manageable by displaying a rounded value instead **Example**> One illusion may beget another. For example, since 0.1 is not exactly 1/10, summing three values of 0.1 may not yield exactly 0.3, either:<jupyter_code>.1 + .1 + .1 == .3
a = .1 + .1 + .1 
b = .3
a, b, a == b<jupyter_output><empty_output><jupyter_text>https://stackoverflow.com/questions/5595425/what-is-the-best-way-to-compare-floats-for-almost-equality-in-pythonOne way to do this is to check if the difference of both is less a value epsilon which we define as 1e-8 (0.00000008)<jupyter_code>e = 1e-8
e
abs(a-b) < e<jupyter_output><empty_output><jupyter_text>Abstracting this info a function<jupyter_code>def is_close(no1, no2, e=1e-8):
    return abs(a-b) <= e
is_close(a,b)<jupyter_output><empty_output><jupyter_text>There is one problem with thisepsilon does not consider the magnitude. Here is modification of an example copied from the stack overflow post mentioned above.<jupyter_code>a = .000000000000000000000000000000000004 #we clearly know a and b are different
b = .000000000000000000000000000000000003
e = .000000000000000000000000000000000001
is_close(a,b,e)
abs(a-b)<jupyter_output><empty_output><jupyter_text>Implementation in libraries<jupyter_code>def isclose_lib(a, b, rel_tol=1e-9, abs_tol=0.0):
    return abs(a-b) <= max( rel_tol * max(abs(a), abs(b)), abs_tol )
isclose_lib(a,b)<jupyter_output><empty_output><jupyter_text>disecting the function further<jupyter_code>max(abs(a), abs(b))
#4e-26 is a
a
rel_tol=1e-9 
rel_tol * a
0.000000000000000000000000000000000000000000004<jupyter_output><empty_output><jupyter_text>the episilon value changes depending on bigger number<jupyter_code>a = .4
b = .3

max(abs(a), abs(b))
a
rel_tol=1e-9 
rel_tol * a
.0000000040000000000000007<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09690157958687728, 'fraction_numerical': 0.09872417982989064, 'mean_word_length': 5.639112903225806, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 41, 'https://': 5, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 8, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '518057', 'license': 'MIT', 'n_tokens_mistral': 1301, 'n_tokens_neox': 1038, 'n_words': 345, 'path': 'Colab Notebooks/20191020_comparing_floats.ipynb', 'repo_name': 'ankschoubey/notes', 'size': '3292'}