HOWTO · Python

TypeError: 'float' オブジェクトを Python で整数として解釈できない問題を修正

Python の `TypeError: 'float' object cannot be interpreted as an integer` を解決するため、`range()` を使う前に float を整数へ変換し、意図する反復回数に合った変換方法を選ぶ方法を説明します。

このページの内容

TypeError: 'float' object cannot be interpreted as an integer と表示された場合、整数が必要な場所に浮動小数点数が渡されています。よくある原因は、小数値を range() に渡すことです。意図する反復回数に応じて値を変換してください。変換方法によってループの回数が変わります。

range() に浮動小数点数を渡すとこの TypeError が発生する理由

range() は整数のシーケンスを作るため、開始値、終了値、ステップ幅には整数、または Python の整数インデックスプロトコルを実装した整数相当のオブジェクトが必要です。3.0 のように小数部分がゼロの浮動小数点数も受け付けられません。小数部分がゼロでも float であり、int ではないためです。たとえば、range(3.5) は TypeError: 'float' object cannot be interpreted as an integer を発生させます。

Python では整数と浮動小数点数は別の型です。3 の型は int、3.5 の型は float です。後続のループで整数の回数が必要でも、計算結果が浮動小数点数になることがあります。このエラーは range() の呼び出しで型が合わないことを示しており、Python が浮動小数点数を保存したり計算したりできないという意味ではありません。

range() を使う前に浮動小数点数を整数へ変換する

回数を range() に渡す前に変換し、その回数が何を表すかに応じて方法を選びます。組み込みの int() はインポートなしで使えます。小数部分をゼロ方向に切り捨てるため、int(3.7) は 3、int(-3.7) は -3 になります。最も近い整数への丸めではありません。値が測定量や計算で求めた上限を表す場合は、切り捨てによって意図した反復回数になるかを確認してください。

math.floor() と math.ceil() は Python 標準ライブラリの math モジュールで使えるため、パッケージのインストールは不要です。import math と記述します。math.floor() は入力値以下の最大の整数を返し、math.ceil() は入力値以上の最小の整数を返します。3.7 の場合、floor は 3、ceil は 4 です。-3.7 の場合、floor は -4、ceil は -3 です。変換後の数値をループの回数に使う場合、この違いが重要です。負の値を切り下げるとゼロから遠ざかりますが、int() はゼロに近づけます。

値を変換する前に、それが何を数えているのか、端数が何を意味するのか、上限に最後の端数分を含めるべきかを考えてください。再試行の上限、ページ数、処理するレコード数では、それぞれ適切なルールが異なることがあります。変換によって他の計算に必要な精度が失われないよう、元の測定値も保持してください。次の短いプログラムでは、選んだ整数の回数を通常のシーケンスに適用します。

この例を実行してください。表示されるラベルと出力は、コード例との一致を保つため英語のままです。

import math

count = 3.7
truncated = int(count)
rounded_up = math.ceil(count)
print("int:", truncated)
print("ceil:", rounded_up)
for index in range(truncated):
    print(index)
int: 3
ceil: 4
0
1
2

必要な結果に応じて int()、math.floor()、math.ceil() を選ぶ

小数部分をゼロ方向に切り捨てるのが意図したルールなら、int() を使います。回数を元の値以下にしたい場合は math.floor()、元の値以上にしたい場合は math.ceil() を使います。正の入力では int() と math.floor() の結果は同じですが、負の非整数では異なります。どれか一つが常に正しいわけではありません。浮動小数点数が時間、処理する量、上限のどれを表すかを考え、意図した回数になるルールを選んでください。

有限の浮動小数点数に対して、この3つの変換はいずれも整数を返すため、その結果を range() に渡せます。一方、どの方法も小数部分の情報を失うため、後の計算で必要なら元の浮動小数点数も別に保持してください。値が本来整数の回数を表すなら、回数を黙って変えてしまう前に、値の取得元を修正するか、変換前に検証するほうが適切な場合もあります。

変換後の値とループの出力を確認する

変換後の回数だけでなく、ループが出力する値も確認してください。range(n) は 0 から始まり、1 ずつ増え、n の手前で終了します。そのため、回数が 3 なら 0、1、2 が生成され、反復は3回です。回数が 0 なら反復はなく、既定の正のステップ幅では終了値が負の場合も値は生成されません。こうした動作から、変換によってプログラムが実行する処理が変わったかどうかを確認できます。

例の出力には int: 3 と ceil: 4 が表示され、その後にループの値 0、1、2 が続きます。int: と ceil: のラベルは、コードとの一致を保つため英語のままです。この出力で、3.7 を切り捨てた影響を確認できます。別の入力を試すには、count を置き換え、変換結果を意図したルールと比べてください。負の入力では、終了値に使う前に int(count)、math.floor(count)、math.ceil(count) の結果を比較します。適切な修正は、単に TypeError を消す変換ではなく、意図した反復回数になる変換です。