Python / float() / 値を浮動小数点数に変換する方法

Pythonのfloat()は数値や対応する数値文字列を浮動小数点数に変換します。引数を省略すると0.0ですが、空文字列やNoneを自動的に0へ変換するわけではありません。変換成功後も、有限な値か、必要な十進精度を満たすかは別に確認します。

基本変換と元の値の型

float(value)は結果を返し、元の変数の型は変更しません。浮動小数点は有限のビットで数量を表し、小数を近似する場合があります。小数点が表示されるかだけで型や精度を判断しないでください。対応入力はfloat()の公式資料を参照します。

例はPython 3と標準ライブラリだけを使います。UTF-8のfloat_example.pyに全体を保存し、python float_example.py、環境によってはpython3で実行します。後の例もファイルを置き換えて独立して実行できます。

value = 3
converted = float(value)
print(converted, type(converted).__name__)
print(value, type(value).__name__)
print(float("  -2.5  "))
print(float("1e3"))
print(float())
print(float(True))

期待される出力:

3.0 float
3 int
-2.5
1000.0
0.0
1.0

元のvalueは整数のままです。前後の空白、符号、1e3のような指数表記も解釈します。Trueは1.0になるので、真偽値を受け付けない入力では別途拒否します。

入力形式とValueError・TypeError

通常の数値文字列は小数点に.を使います。桁区切り、小数点カンマ、通貨記号を自動処理しません。不正な数値文字列はValueError、Noneのような非対応オブジェクトはTypeErrorになります。

for value in ("1,234.5", "2,5", "", None):
    try:
        print(float(value))
    except (ValueError, TypeError) as error:
        print(type(error).__name__)
ValueError
ValueError
ValueError
TypeError

カンマを無条件で削除すると、小数の意図だった2,5が25になり得ます。入力形式と地域ルールを先に決め、確認した規則に沿って正規化します。空欄をエラーか欠損値として扱うか決め、実際の0と区別を失わないようにします。

0.1と0.2の和が0.3と一致しない理由

多くの環境では二進浮動小数点で保存します。一部の十進小数は有限の二進小数で表せず、近い値になります。これは変換失敗ではなく表現上の限界です。Pythonの浮動小数点解説で仕組みを確認できます。

import math
from decimal import Decimal

result = 0.1 + 0.2
print(result)
print(result == 0.3)
print(math.isclose(result, 0.3))
print(Decimal("0.1") + Decimal("0.2"))
0.30000000000000004
False
True
0.3

近似比較にはmath.isclose()を使えますが、許容誤差は単位や必要精度に合わせます。0付近ではabs_tolも検討します。十進計算の正確さが必要なら元の十進文字列からDecimalを生成する方法を検討します。Decimal(0.1)は既に近似された二進値から始まるため同じではありません。

NaN・無限大・範囲超過を確認する

float()はnanやinfも受け付けます。NaNはNot a Numberの略で、infは無限大です。変換できても有限な測定値とは限らないため、必要ならmath.isfinite()で確認します。

import math

for text in ("nan", "inf", "-inf", "2.5"):
    number = float(text)
    print(text, math.isfinite(number))
nan False
inf False
-inf False
2.5 True

非常に大きい指数文字列は無限大になり、大きすぎる整数の変換ではOverflowErrorになる場合があります。NaNは自分自身とも等しく比較されないため、x == float("nan")では検出しません。NaNだけの判定にはmath.isnan()を使います。

print(float("1e400"))
try:
    print(float(10 ** 400))
except OverflowError:
    print("OverflowError")
print(float("nan") == float("nan"))
inf
OverflowError
False

有限な値だけ受け取る関数

変換例外と有限性の確認を組み合わせます。次の関数は不正形式と非有限値を区別し、成功時だけfloatを返します。英語のエラー文は例なので利用者向けの表現へ変更できます。

import math

def finite_number(text):
    try:
        number = float(text)
    except (ValueError, TypeError) as error:
        raise ValueError("not a number") from error
    if not math.isfinite(number):
        raise ValueError("not finite")
    return number

for text in ("2.5", "nan", "abc"):
    try:
        print(finite_number(text))
    except ValueError as error:
        print(error)
2.5
not finite
not a number

この関数が確認するのは有限性までです。年齢・個数・比率などは上下限や整数かどうかも検証します。すべての失敗を0.0で隠すと不正入力と本当の0を区別できなくなります。