Pythonの数値型 float(浮動小数点数)は、3.14 や -0.5 といった通常の数値に加え、「無限大」や「非数 (Not a Number)」といった特殊な状態を表現できます。
これらは、数学的な計算(ゼロ除算の試み)や、データ分析における欠損値の処理などで利用されます。
この記事では、inf (無限大) と nan (非数) の作成方法、それらの演算における振る舞い、そして判定方法について解説します。
無限大 (inf) の作成と性質
無限大(Infinity)は、float('inf') という文字列を float コンストラクタに渡すことで作成できます。
# 正の無限大
pos_inf = float('inf')
# 負の無限大
neg_inf = float('-inf')
print(f"正の無限大: {pos_inf}")
print(f"負の無限大: {neg_inf}")
print(f"型: {type(pos_inf)}")
実行結果:
正の無限大: inf
負の無限大: -inf
型: <class 'float'>
math モジュールをインポートすれば、math.inf として直接利用することも可能です。
inf の演算
無限大は、ほとんどの演算において無限大のままです。
# 無限大に数を足しても無限大
print(f"inf + 10000 = {pos_inf + 10000}")
# 無限大に数を掛けても無限大
print(f"inf * 500 = {pos_inf * 500}")
# 無限大を(有限の)数で割っても無限大
print(f"inf / 123 = {pos_inf / 123}")
# 無限大同士の加算
print(f"inf + inf = {pos_inf + pos_inf}")
実行結果:
inf + 10000 = inf
inf * 500 = inf
inf / 123 = inf
inf + inf = inf
非数 (nan) の作成と性質
非数(Not a Number)は、float('nan') で作成できます。nan は、計算結果が「(実数として)定義できない数値」であることを示すために使われます。
nan が発生するケース
nan は、以下のような数学的に「不定形」となる計算で発生します。
# 0.0 / 0.0
nan_val_1 = 0.0 / 0.0
# inf - inf
nan_val_2 = float('inf') - float('inf')
# inf / inf
nan_val_3 = float('inf') / float('inf')
print(f"0.0 / 0.0 = {nan_val_1}")
print(f"inf - inf = {nan_val_2}")
print(f"inf / inf = {nan_val_3}")
実行結果:
0.0 / 0.0 = nan
inf - inf = nan
inf / inf = nan
nan の演算(伝播性)
nan は「伝播性」を持ちます。nan が含まれる演算の結果は、ほぼ全て nan になります。
base_nan = float('nan')
print(f"nan + 50 = {base_nan + 50}")
print(f"nan * 0 = {base_nan * 0}") # 0を掛けても nan
実行結果:
nan + 50 = nan
nan * 0 = nan
inf と nan の判定方法
inf や nan はデータ処理において特別な対応が必要な場合が多いため、これらを正しく判定する方法が重要です。判定には math モジュールを使います。
import math
val_inf = float('inf')
val_nan = float('nan')
val_num = 100.0
# isinf() : 無限大かどうかを判定
print(f"math.isinf({val_inf}): {math.isinf(val_inf)}") # True
print(f"math.isinf({val_num}): {math.isinf(val_num)}") # False
# isnan() : 非数かどうかを判定
print(f"math.isnan({val_nan}): {math.isnan(val_nan)}") # True
print(f"math.isnan({val_inf}): {math.isnan(val_inf)}") # False
nan 判定における最重要注意点
nan を判定する際、== 演算子を使ってはいけません。nan は**自分自身と比較しても等しくならない(False を返す)**という特殊な性質を持っています。
test_nan = float('nan')
# '==' を使った誤った判定
print(f"test_nan == float('nan') : {test_nan == float('nan')}") # False
print(f"test_nan == test_nan : {test_nan == test_nan}") # False
nan かどうかを確実に判定するには、必ず math.isnan() を使用してください。
実用例:安全なデータ集計
データリストに inf や nan が含まれている場合、sum() などが意図通りに動作しません。これらを判定して除外する処理の例です。
import math
def calculate_safe_average(data_list):
"""
inf や nan を除外して平均値を計算する
"""
total = 0
count = 0
for value in data_list:
# inf や nan を判定してスキップ
if math.isinf(value) or math.isnan(value):
print(f"スキップ: {value}")
continue
total += value
count += 1
if count == 0:
return 0.0 # または nan を返す
return total / count
# --- 実行 ---
raw_data = [15.5, 20.0, float('inf'), 10.0, float('nan'), 5.5, float('-inf')]
average = calculate_safe_average(raw_data)
print(f"処理済みデータ: {raw_data}")
print(f"安全な平均値: {average}")
実行結果:
スキップ: inf
スキップ: nan
スキップ: -inf
処理済みデータ: [15.5, 20.0, inf, 10.0, nan, 5.5, -inf]
安全な平均値: 12.75
まとめ
- 無限大は
float('inf')またはmath.infで作成します。 - 非数(Not a Number)は
float('nan')またはmath.nanで作成します。0/0やinf-infなどの不定形の計算結果としても生じます。 infやnanの判定には、math.isinf()とmath.isnan()を使用します。nan == nanはFalseになるため、==でnanを判定してはいけません。
