{"id":8145,"date":"2023-09-08T13:43:49","date_gmt":"2023-09-08T08:13:49","guid":{"rendered":"https:\/\/tutorpython.com\/?p=8145"},"modified":"2023-10-19T15:14:27","modified_gmt":"2023-10-19T09:44:27","slug":"python-mathisclose","status":"publish","type":"post","link":"https:\/\/tutorpython.com\/python-mathisclose","title":{"rendered":"Python math.isclose"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">In This Article<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/tutorpython.com\/python-mathisclose\/#The_problem_with_using_for_float_comparison\" >The problem with using == for float comparison<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/tutorpython.com\/python-mathisclose\/#The_solution_Python_mathisclose_function\" >The solution: Python\u00a0 math.isclose function<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/tutorpython.com\/python-mathisclose\/#Examples_of_using_Python_mathisclose_for_float_comparison\" >Examples of using Python math.isclose for float comparison<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/tutorpython.com\/python-mathisclose\/#Python_Comparing_two_float_values_with_default_tolerances\" >Python Comparing two float values with default tolerances<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/tutorpython.com\/python-mathisclose\/#Python_Comparing_two_float_values_with_custom_tolerance_values\" >Python Comparing two float values with custom tolerance values<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<p>In this comprehensive Python tutorial, we&#8217;ll explore the intricacies of comparing float values, shedding light on why relying on the<a href=\"https:\/\/tutorpython.com\/tutorial\/types-of-operators-in-python\" target=\"_blank\" rel=\"noopener\"> &#8216;==&#8217; operator<\/a> for such comparisons can often yield unexpected outcomes. We&#8217;ll then introduce a robust solution: <a href=\"https:\/\/tutorpython.com\/tutorial\/python-mathisclose\">Python math.isclose function<\/a>.<\/p>\n<p>When delving into the realm of scientific computations in Python, one frequently encounters float values. However, comparing these values can be a daunting task due to the idiosyncrasies of how computers represent them.<\/p>\n<p>Prepare to enhance your Python programming skills by mastering the art of precise float comparison. Let&#8217;s embark on this journey together, with &#8216;Python math.isclose&#8217; as our guiding beacon.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_problem_with_using_for_float_comparison\"><\/span>The problem with using <code>==<\/code> for <code>float<\/code> comparison<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Internally, Python represents a <code>float<\/code> value using a finite binary representation. If we run the following code to print <code>0.1<\/code>,<\/p>\n<pre><code class=\"language-python line-numbers\">print(0.1)\r\n<\/code><\/pre>\n<p>We get the output<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-8657 size-full\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_01-e1693405501805.png\" alt=\"output of float 0.1 print\" width=\"959\" height=\"51\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_01-e1693405501805.png 959w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_01-e1693405501805-300x16.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_01-e1693405501805-768x41.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_01-e1693405501805-600x32.png 600w\" sizes=\"(max-width: 959px) 100vw, 959px\" \/><\/p>\n<p>However, if we want to see more of the fractional part, we can display it with 30 decimal places of precision.<\/p>\n<pre><code class=\"language-python line-numbers\">print(f\"{float(0.1):.30f}\")\r\n<\/code><\/pre>\n<p>we will get more details about the fractional part.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-8658 size-full\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_format_01-e1693406690989.png\" alt=\"output of 0.1 formatted as a string with a precision 30 decimal places\" width=\"960\" height=\"49\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_format_01-e1693406690989.png 960w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_format_01-e1693406690989-300x15.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_format_01-e1693406690989-768x39.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/output_format_01-e1693406690989-600x31.png 600w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>Now we can see that internally, <code>0.1<\/code> is not represented as an exact value because it is represented internally using binary. Binary can only give an exact representation if the fractional number is a power of two or a sum of powers of two. For example:<\/p>\n<pre><code class=\"language-python line-numbers\"># print 0.5 formatted as a string with 30 digits \r\n# after the decimal place\r\nprint(f\"{float(0.5):.30f}\")\r\n\r\n# evaluate 0.5+0.25 and print the result formatted \r\n# as a string with 30 digits after the decimal place\r\nprint(f\"{float(0.5+0.25):.30f}\")\r\n\r\n# evaluate 0.5+0.125 and print the result formatted \r\n# as a string with 30 digits after the decimal place\r\nprint(f\"{float(0.5+0.125):.30f}\")\r\n<\/code><\/pre>\n<p>The output is as follows:<\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter wp-image-8659 size-full\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-1-e1693407598213.png\" alt=\"display powers of two or sum of powers of two with a precision 30 decimal place\" width=\"960\" height=\"102\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-1-e1693407598213.png 960w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-1-e1693407598213-300x32.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-1-e1693407598213-768x82.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-1-e1693407598213-600x64.png 600w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>From the output, we see that in this case, the representation is exact.<\/p>\n<p>However, Python can only represent <code>float<\/code> values like <code>0.1<\/code> approximately.<\/p>\n<p>This raises a problem when trying to carry out comparisons using the <code>==<\/code> operator. The following code snippet illustrates the issue.<\/p>\n<pre><code class=\"language-python line-numbers\">expr = 0.5 + 0.125\r\nnum = 0.625\r\n\r\nprint(f\"0.5 + 0.125 (to 30dp) gives {expr:.30f}\")\r\nprint(f\"0.625 (to 30 dp) gives {num:.30f}\")\r\nprint(f\"expr==num evaluates to {expr==num}\")\r\n<\/code><\/pre>\n<p>The output we get is:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-8660 size-full\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-2-e1693408721340.png\" alt=\"output for exact comparison with == returns true\" width=\"960\" height=\"78\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-2-e1693408721340.png 960w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-2-e1693408721340-300x24.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-2-e1693408721340-768x62.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-2-e1693408721340-600x49.png 600w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>From our output, we can see that the internal representation of <code>0.625<\/code> and the sum <code>0.5 + 0.125<\/code> are the same. So, comparison returns <code>True<\/code>.<\/p>\n<p>The situation changes when we work with <code>float<\/code> values that are approximately represented internally, as the next code snippet shows.<\/p>\n<pre><code class=\"language-python line-numbers\">expr = 0.1 + 0.2\r\nnum = 0.3\r\n\r\nprint(f\"0.1 + 0.2 (to 30dp) gives {expr:.30f}\")\r\nprint(f\"0.3 (to 30 dp) gives {num:.30f}\")\r\nprint(f\"expr==num evaluates to {expr==num}\")\r\n<\/code><\/pre>\n<p>The output is as follows:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-8661 size-full\" src=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-3-e1693409528373.png\" alt=\"display of comparison using == on inexact values of float\" width=\"960\" height=\"107\" srcset=\"https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-3-e1693409528373.png 960w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-3-e1693409528373-300x33.png 300w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-3-e1693409528373-768x86.png 768w, https:\/\/tutorpython.com\/wp-content\/uploads\/2023\/04\/Untitled-drawing-3-e1693409528373-600x67.png 600w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><\/p>\n<p>The comparison returns <code>False<\/code> since the sum stored in <code>expr<\/code> is represented differently from the value stored in <code>num<\/code>, even if we intended to hold the same value of <code>0.3<\/code> in both variables.<\/p>\n<p>The approximate representation of <code>float<\/code> values make comparing them using the <code>==<\/code> operator unpredictable. Serious bugs could result if a situation similar to the above scenario occurred in our code. However, Python provides an alternative way that allows us to compare <code>float<\/code> values without running into this kind of bug.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_solution_Python_mathisclose_function\"><\/span>The solution: Python\u00a0 <code>math.isclose<\/code> function<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Python <strong>version 3.5<\/strong> introduced the <code>math.isclose<\/code> function to address this challenge that arises when <code>float<\/code> values are compared. Instead of checking if the two numbers compared are the same, <code>math.isclose<\/code> checks if they are close to each other within a specified tolerance value.<\/p>\n<p>The <code>math.isclose<\/code> Python function is called like so:<\/p>\n<pre><code class=\"language-python line-numbers\">math.isclose(a, b, rel_tol, abs_tol)<\/code><\/pre>\n<p>Each <a href=\"https:\/\/tutorpython.com\/tutorial\/function-arguments-in-python\" target=\"_blank\" rel=\"noopener\">parameter<\/a> is explained below:<\/p>\n<ul>\n<li><code>a<\/code> : The <strong>first value<\/strong> to compare for closeness (Required)<\/li>\n<li><code>b<\/code> : The <strong>second value<\/strong> to compare for closeness (Required)<\/li>\n<li><code>rel_tol<\/code> : The<strong> relative tolerance<\/strong>. The maximum allowed difference between <code>a<\/code> and <code>b<\/code> , relative to the bigger value compared. It has a default value of <code>1e-09<\/code> (Optional)<\/li>\n<li><code>abs_tol<\/code> : The <strong>absolute tolerance<\/strong>. The maximum allowed difference between <code>a<\/code> and <code>b<\/code> . It has a default value of <code>0.0<\/code><\/li>\n<\/ul>\n<p>The function carries out the following calculation when doing comparisons:<\/p>\n<pre><code class=\"language-python line-numbers\">abs_a, abs_b = abs(a), abs(b)\r\nabs_tol_rel = rel_tol * max(abs_a, abs_b)\r\n\r\n# The comparison...\r\nabs(a - b) &lt;= max(abs_tol_rel, abs_tol)\r\n<\/code><\/pre>\n<p>If <code>a<\/code> and <code>b<\/code> are close, the comparison returns <code>True<\/code>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Examples_of_using_Python_mathisclose_for_float_comparison\"><\/span>Examples of using Python <code>math.isclose<\/code> for <code>float<\/code> comparison<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In the previous sections, we discussed the challenges of comparing <code>float<\/code> values using the equality operator, and how we could make use of an alternative, <code>math.isclose<\/code>, to check if two <code>float<\/code> numbers are close enough within a specific tolerance value. In this section, we will dive into examples of making use of <code>math.isclose<\/code>.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Python_Comparing_two_float_values_with_default_tolerances\"><\/span>Python Comparing two <code>float<\/code> values with default tolerances<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The <code>math.isclose<\/code> function is defined with a default\u00a0 <code>rel_tol<\/code>value of <code>1e-09<\/code> and a default <code>abs_tol<\/code> value of <code>0.0<\/code>. The next example will make use of these default tolerance settings to compare two <a href=\"https:\/\/tutorpython.com\/tutorial\/data-types-in-python\" target=\"_blank\" rel=\"noopener\"><code>float<\/code> values<\/a>.<\/p>\n<pre><code class=\"language-python line-numbers\">from math import isclose\r\n\r\na = 0.1 + 0.1 + 0.1\r\nb = 0.3\r\n\r\nprint(isclose(a, b))  # Output: True\r\n<\/code><\/pre>\n<p>In the example, we used <code>math.isclose<\/code> to check if the sum <code>0.1 + 0.1 + 0.1<\/code> and the <code>float<\/code> literal <code>0.3<\/code> are close based on the default settings. The code <a href=\"https:\/\/tutorpython.com\/tutorial\/basic-input-output-operations-in-python\" target=\"_blank\" rel=\"noopener\">prints<\/a> out <code>True<\/code> which means that their internal representations are as close as allowed by the default tolerance values.<\/p>\n<p>On the other hand, we will get a return value of <code>False<\/code> if we use <code>isclose<\/code>with default tolerance values to check if <code>1e-10<\/code> and <code>1e-11<\/code> are close.<\/p>\n<pre><code class=\"language-python line-numbers\">result = isclose(1e-10, 1e-11)\r\n\r\nprint(result)  # Output: False\r\n<\/code><\/pre>\n<p>From the tolerance formula discussed in the section that defines <code>math.isclose<\/code>, the absolute difference between <code>1e-10<\/code> and <code>1e-11<\/code> should be smaller than <code>max(rel_tol * max(1e-10, 1e-11), abs_tol)<\/code>.<\/p>\n<p>The absolute difference between <code>1e-10<\/code> and <code>1e-11<\/code> (a value of <code>9e-11<\/code>) is not smaller than the value returned by <code>max(rel_tol * max(1e-10, 1e-11), abs_tol)<\/code> (which is <code>1.0000000000000001e-19<\/code>).<\/p>\n<p>Therefore, <code>isclose<\/code> returns <code>False<\/code> for the comparison between <code>1e-10<\/code> and <code>1e-11<\/code>using the default tolerance values. Thus, the current tolerance values are not sufficient to consider <code>1e-10<\/code> and <code>1e-11<\/code> close.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Python_Comparing_two_float_values_with_custom_tolerance_values\"><\/span>Python Comparing two <code>float<\/code> values with custom tolerance values<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The default tolerance values work for many situations.<\/p>\n<p>However, <a href=\"https:\/\/tutorpython.com\/tutorial\/function-arguments-in-python\" target=\"_blank\" rel=\"noopener\">different values can be passed<\/a> to <code>math.isclose<\/code> to suit specific requirements.<\/p>\n<p>Let&#8217;s explore examples that pass different values for <code>rel_tol<\/code> and <code>abs_tol<\/code>.<\/p>\n<p>Hers an example that compares two values <code>1000.0<\/code> and <code>1001.0<\/code> using <code>rel_tol<\/code> value <code>1e-5<\/code>. Running the code snippet will show how the comparison plays out.<\/p>\n<pre><code class=\"language-python line-numbers\">from math import isclose\r\n\r\nresult = isclose(1000.0, 1001.0, rel_tol=1e-5)\r\n\r\nprint(result)  # Output: False\r\n<\/code><\/pre>\n<p>Here, <code>math.isclose<\/code> returns <code>False<\/code> because the absolute difference between <code>1000.0<\/code> and <code>1001.0<\/code> relative to the magnitude of the bigger number <code>1001.0<\/code>does not fall within the specified relative tolerance.<\/p>\n<p>This next example finds out if the sum <code>0.1 + 0.2<\/code> is within <code>1e-10<\/code> of <code>0.3<\/code>.<\/p>\n<pre><code class=\"language-python line-numbers\">from math import isclose\r\n\r\nresult = isclose(0.1+0.2, 0.3, abs_tol=1e-10)\r\n\r\nprint(result)  # Output: True\r\n<\/code><\/pre>\n<p><code>math.isclose<\/code> returns <code>True<\/code> since the absolute difference between the internal representation of the result of <code>0.1 + 0.2<\/code> and the internal representation of <code>0.3<\/code>\u00a0 is smaller than<code>1e-10<\/code> (the <code>abs_tol<\/code>).<\/p>\n<p>In conclusion <code>math.isclose<\/code> offers a solution arising when trying to compare <code>float<\/code> values. Instead of directly checking for equality<span style=\"font-size: 0.875rem;\">, the function checks if the absolute difference of the compared values falls under a tolerance value, effectively overcoming rounding errors and precision issues.<\/span><\/p>\n<p><span style=\"font-size: 0.875rem;\"> Understanding the use of <\/span><code style=\"font-size: 0.875rem;\">math.isclose<\/code><span style=\"font-size: 0.875rem;\"> is crucial if we want to avoid bugs when carrying out float comparisons in our code. If you liked this tutorial, please consider checking out other tutorials like this on our website that can help you in your coding journey.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this comprehensive Python tutorial, we&#8217;ll explore the intricacies of comparing float&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[28],"tags":[],"class_list":["post-8145","post","type-post","status-publish","format-standard","hentry","category-tutorial"],"acf":[],"_links":{"self":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/comments?post=8145"}],"version-history":[{"count":16,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8145\/revisions"}],"predecessor-version":[{"id":8860,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/posts\/8145\/revisions\/8860"}],"wp:attachment":[{"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/media?parent=8145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/categories?post=8145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tutorpython.com\/wp-json\/wp\/v2\/tags?post=8145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}