How to Compare Floating-Point Numbers in Python: Using math.isclose() to Handle Precision Errors

When handling decimal numbers in computers, they are represented in binary internally, which inevitably causes minute “calculation errors.” Therefore, comparing floating-point numbers (float) using the == operator may not yield the expected result.

To solve this problem, Python 3.5 introduced the isclose() function in the standard math library.

This article explains the problems that occur when comparing floating-point numbers and the correct method using math.isclose().

目次

The Problem with Floating-Point Comparison

First, let’s try comparing the result of a simple addition. 0.1 + 0.2 should be 0.3, but in Python (and many other programming languages), it evaluates to False.

# Calculate 0.1 + 0.2
calc_result = 0.1 + 0.2

expected_value = 0.3

print(f"Calculation Result: {calc_result}")
print(f"Expected Value: {expected_value}")

# Compare with equality operator (==)
is_equal = (calc_result == expected_value)
print(f"Strict Comparison (==): {is_equal}")

Execution Result:

Calculation Result: 0.30000000000000004
Expected Value: 0.3
Strict Comparison (==): False

The calculation result becomes 0.30000000000000004, which is slightly different from 0.3, so the equality check returns False. This is the problem caused by floating-point errors.

Solution with math.isclose()

The math.isclose() function determines if two values are “close enough (within a tolerance).” This allows you to treat them as “practically equal” by accepting minute errors.

Syntax:

import math

math.isclose(a, b, rel_tol=1e-09, abs_tol=0.0)

Basic Usage

Let’s rewrite the previous example using math.isclose().

import math

val_a = 0.1 + 0.2
val_b = 0.3

# Compare with isclose
is_close = math.isclose(val_a, val_b)

print(f"Comparison with math.isclose: {is_close}")

Execution Result:

Comparison with math.isclose: True

Even with the default settings, it absorbs general calculation errors and returns True (equal).

Setting Tolerance

You can finely control how much error math.isclose() allows using arguments.

1. Relative Tolerance (rel_tol)

rel_tol (relative tolerance) specifies the allowed error as a ratio (like a percentage) of the input value’s magnitude. The default is 1e-09 (1 in 1 billion).

import math

target = 100.0
# Value with an error of 0.1 relative to 100.0
value = 100.1

# Setting to allow 1% (0.01) error
is_close_loose = math.isclose(value, target, rel_tol=0.01)

# Setting to allow only 0.01% (0.0001) error
is_close_strict = math.isclose(value, target, rel_tol=0.0001)

print(f"1% Tolerance: {is_close_loose}")     # True
print(f"0.01% Tolerance: {is_close_strict}") # False

2. Absolute Tolerance (abs_tol)

abs_tol (absolute tolerance) allows a fixed numerical difference regardless of the value’s magnitude. This is effective when comparing very small numbers close to zero, where the default relative tolerance defaults to 0.

import math

near_zero_a = 0.00001
near_zero_b = 0.00002

# Since relative tolerance might fail near zero,
# set absolute tolerance to allow differences within 0.0001
is_close_zero = math.isclose(near_zero_a, near_zero_b, abs_tol=0.0001)

print(f"Comparison near zero: {is_close_zero}")

Execution Result:

Comparison near zero: True

Summary

  • Using == for floating-point numbers (float) may lead to unintended results due to calculation errors.
  • Using math.isclose(a, b) enables correct comparison by considering errors.
  • Specify rel_tol (relative tolerance) or abs_tol (absolute tolerance) to adjust the acceptable range as needed.
  • Using math.isclose() is recommended in programs involving numerical calculations to prevent bugs.
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次