The math.isnan(x) function checks whether a numeric value is NaN (Not a Number), returning True if it is NaN and False otherwise. Because the IEEE 754 standard defines NaN as not equal to anything—including itself (float('nan') == float('nan') evaluates to False)—math.isnan() is the authoritative way to detect undefined numeric results in Python.
Companion Checks: To verify whether numbers represent extreme infinities or standard finite values, see math.isinf() and math.isfinite().
The math.isnan() function is provided by the standard math module:
import math
is_nan = math.isnan(x)
| Parameter | Type | Required? | Description |
|---|---|---|---|
x |
float or int |
Yes | The numeric value to evaluate. Passing an integer always returns False. Passing non-numeric types raises a TypeError. |
Return Value: Returns a boolean True if x represents NaN; otherwise returns False.
A classic pitfall in computer science is attempting to test for NaN using the equality operator (==) or identity operator (is):
val = float("nan")
print(val == val) # False! (NaN is never equal to itself)
print(val == float("nan")) # False!
print(val is float("nan")) # False! (Different memory references)
# The correct and authoritative approach:
import math
print(math.isnan(val)) # True
False
False
False
True
Fun Fact: Because NaN is defined as unequal to itself, an old trick to check if a variable x is NaN without importing math is testing x != x, which evaluates to True exclusively for NaN. However, using math.isnan(x) is vastly preferred for readability and code clarity.
In Python, NaN values arise in two primary ways:
Passing the string "nan" (case-insensitive) to float():
nan1 = float("nan")
nan2 = float("NaN")
nan3 = float("NAN")
Operations involving infinity that have no defined mathematical solution result in NaN:
inf = float("inf")
print(math.isnan(inf / inf)) # True (Infinity divided by Infinity)
print(math.isnan(inf - inf)) # True (Infinity minus Infinity)
print(math.isnan(0 * inf)) # True (Zero multiplied by Infinity)
0 / 0 raises a ZeroDivisionError exception rather than silently producing NaN.
The Python standard library provides three complementary functions to classify any floating-point number:
| Value | math.isnan() |
math.isinf() |
math.isfinite() |
|---|---|---|---|
42.0 (Normal number) |
False |
False |
True |
float('inf') (+∞) |
False |
True | False |
float('-inf') (-∞) |
False |
True | False |
float('nan') (NaN) |
True | False |
False |
When working with numerical lists, NaN values propagate through calculations (e.g. sum([1.0, 2.0, float('nan')]) returns nan). Use a list comprehension to filter out missing or invalid values:
import math
raw_measurements = [10.2, float("nan"), 12.5, 9.8, float("nan"), 11.1]
# Filter out NaN items
clean_data = [x for x in raw_measurements if not math.isnan(x)]
print("Cleaned data: ", clean_data)
print("Average value:", sum(clean_data) / len(clean_data))
Cleaned data: [10.2, 12.5, 9.8, 11.1]
Average value: 10.9
In data analytics, missing numerical entries in Pandas DataFrames are encoded as NaN. While math.isnan() works on single numbers, Pandas and NumPy offer vectorized methods:
math.isnan(val) for individual scalar numbers in pure Python scripts.pd.isna(series) or series.isnull() when checking entire columns in Pandas.df.dropna(), or replace them with defaults using df.fillna().Passing non-numeric types (such as strings or lists) directly to math.isnan() raises a TypeError:
import math
try:
math.isnan("nan") # Passing string rather than float
except TypeError as err:
print("Caught expected type error:", err)
# Output: Caught expected type error: must be real number, not str
Let's construct an automated data cleaning utility that ingests noisy IoT sensor streams, converts values, drops NaNs and infinities, and computes calibrated averages with unit assertions:
import math
def sanitize_telemetry(readings):
clean = []
for item in readings:
try:
val = float(item)
# Keep only real numbers that are not NaN and not Infinite
if not math.isnan(val) and math.isfinite(val):
clean.append(val)
except (ValueError, TypeError):
continue # Ignore corrupted text strings
return clean
sensor_stream = [22.4, float("nan"), 23.1, "DEVICE_OFFLINE", float("inf"), 22.9, float("nan")]
sanitized = sanitize_telemetry(sensor_stream)
# Unit Assertions
assert sanitized == [22.4, 23.1, 22.9]
assert len(sanitized) == 3
assert round(sum(sanitized) / len(sanitized), 2) == 22.8
print("Sanitized readings:", sanitized)
print("All sensor telemetry unit assertions passed successfully!")
Open in Google Colab View on GitHub
Run all math.isnan() examples interactively, test the NaN equality paradox, and verify the telemetry sanitizer with unit assertions directly in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.