python
string-to-float
type-conversion
error-handling
coding-tips

Checking if a string can be converted to float in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Python has no built-in is_float() function. The standard way to check if a string can be converted to a float is to attempt the conversion with float() inside a try/except block. If it raises ValueError, the string is not a valid float. Alternative approaches include regex matching and custom validation functions, but the try/except pattern is the most Pythonic and handles all edge cases (scientific notation, infinity, NaN). This article covers all methods with their trade-offs.

python
1def is_float(value):
2    try:
3        float(value)
4        return True
5    except (ValueError, TypeError):
6        return False
7
8# Test cases
9print(is_float("3.14"))      # True
10print(is_float("-2.5"))      # True
11print(is_float("100"))       # True (integers are valid floats)
12print(is_float("1e10"))      # True (scientific notation)
13print(is_float("inf"))       # True (infinity)
14print(is_float("nan"))       # True (Not a Number)
15print(is_float("hello"))     # False
16print(is_float(""))          # False
17print(is_float("12.34.56"))  # False
18print(is_float(None))        # False (TypeError caught)

The try/except approach is the most reliable because it uses the same float() parser that you would use for the actual conversion. It handles all valid float formats including scientific notation, negative numbers, infinity, and NaN.

Method 2: str.replace + isdigit

python
1def is_float_manual(value):
2    if not isinstance(value, str):
3        return False
4    # Remove leading/trailing whitespace
5    value = value.strip()
6    if not value:
7        return False
8    # Handle negative sign
9    if value[0] in ('+', '-'):
10        value = value[1:]
11    # Check for one decimal point
12    parts = value.split('.')
13    if len(parts) > 2:
14        return False
15    return all(part.isdigit() for part in parts if part)
16
17# Works for simple cases
18print(is_float_manual("3.14"))    # True
19print(is_float_manual("-2.5"))    # True
20print(is_float_manual("hello"))   # False
21
22# Fails for valid float formats
23print(is_float_manual("1e10"))    # False (but float("1e10") works)
24print(is_float_manual("inf"))     # False (but float("inf") works)

This approach is fragile — it misses scientific notation, infinity, and NaN. Prefer try/except unless you need to reject those formats intentionally.

Method 3: Regular Expression

python
1import re
2
3def is_float_regex(value):
4    if not isinstance(value, str):
5        return False
6    pattern = r'^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$'
7    return bool(re.match(pattern, value.strip()))
8
9print(is_float_regex("3.14"))     # True
10print(is_float_regex("-2.5"))     # True
11print(is_float_regex("1e10"))     # True
12print(is_float_regex(".5"))       # True
13print(is_float_regex("hello"))    # False
14print(is_float_regex("inf"))      # False (rejected by regex)
15print(is_float_regex("nan"))      # False (rejected by regex)

Regex gives fine-grained control over what you accept. This pattern handles scientific notation but rejects inf and nan, which may be desirable for data validation.

Converting After Checking

python
1# Pattern: check then convert
2user_input = input("Enter a number: ")
3
4if is_float(user_input):
5    value = float(user_input)
6    print(f"You entered: {value}")
7else:
8    print("Invalid number")
9
10# Better: just convert and handle the error
11try:
12    value = float(user_input)
13    print(f"You entered: {value}")
14except ValueError:
15    print("Invalid number")

If you are going to convert anyway, skip the check and just handle the exception. Checking first and then converting calls float() twice.

Handling Special Values

python
1import math
2
3def is_numeric_float(value):
4    """Check if string is a finite float (rejects inf, nan)."""
5    try:
6        f = float(value)
7        return math.isfinite(f)
8    except (ValueError, TypeError):
9        return False
10
11print(is_numeric_float("3.14"))   # True
12print(is_numeric_float("inf"))    # False
13print(is_numeric_float("nan"))    # False
14print(is_numeric_float("-inf"))   # False
15print(is_numeric_float("1e308"))  # True
16print(is_numeric_float("1e309"))  # False (overflows to inf)

Use math.isfinite() after conversion to reject infinity and NaN if your application requires finite numbers only.

Batch Validation

python
1data = ["3.14", "hello", "42", "", "1e5", "nan", "7.0"]
2
3# Filter valid floats
4valid = [float(x) for x in data if is_float(x)]
5print(valid)  # [3.14, 42.0, 100000.0, nan, 7.0]
6
7# Filter valid finite floats
8import math
9finite = [float(x) for x in data if is_float(x) and math.isfinite(float(x))]
10print(finite)  # [3.14, 42.0, 100000.0, 7.0]
11
12# With pandas
13import pandas as pd
14s = pd.Series(data)
15numeric = pd.to_numeric(s, errors='coerce')
16print(numeric)
17# 0      3.14
18# 1       NaN  (was "hello")
19# 2     42.00
20# 3       NaN  (was "")
21# 4  100000.0
22# 5       NaN  (was "nan" string)
23# 6      7.00

pd.to_numeric(errors='coerce') converts valid values and replaces invalid ones with NaN, which is often cleaner than manual filtering.

Common Pitfalls

  • "nan" and "inf" are valid floats: float("nan") and float("inf") do not raise exceptions. If you need only finite numbers, check with math.isfinite() after conversion.
  • Whitespace handling: float(" 3.14 ") works (strips whitespace automatically), but float("3 .14") raises ValueError. Leading/trailing whitespace is fine, embedded whitespace is not.
  • Locale-specific decimal separators: float("3,14") raises ValueError because Python uses . as the decimal separator. For locale-aware parsing, use locale.atof().
  • Checking then converting is redundant: Calling is_float(x) then float(x) parses the string twice. If you need the value, just convert inside try/except.
  • Empty strings and None: float("") raises ValueError and float(None) raises TypeError. The try/except approach handles both, but regex or manual checks may miss TypeError.

Summary

  • Use try: float(value) / except ValueError as the standard check — it handles all valid formats
  • Use math.isfinite() after conversion to reject infinity and NaN
  • Regex gives fine-grained control but misses edge cases that float() handles
  • Manual string checks (isdigit, replace) are fragile and miss scientific notation
  • For batch data, use pd.to_numeric(errors='coerce') to convert valid values and NaN-fill invalid ones
  • If you need the value anyway, skip the check and just handle the exception directly

Course illustration
Course illustration

All Rights Reserved.