Pythonの整数intと小数floatの違い・使い分け・計算方法

Pythonの数値型は大きく整数のintと小数のfloatに分かれます。

両者は見た目が似ていても内部表現や得意分野が異なるため、正しく使い分けることが重要です。

本稿では、基礎から計算方法、型変換、精度の落とし穴、表示フォーマットや実用Tipsまで、実行例を交えて丁寧に解説します。

目次
  1. Pythonの整数intと小数floatの基礎
  2. intとfloatの違い・使い分けの基準
  3. 計算方法の基本:演算子と挙動の違い
  4. 型変換と比較のコツ【型変換と精度の注意点】
  5. 精度と誤差の注意点【floatの落とし穴】
  6. 表示フォーマットと実用Tips
  7. まとめ

Pythonの整数intと小数floatの基礎

intの特徴:任意精度整数と典型的な用途

Pythonのintは任意精度整数です。

桁数に理論上の上限はなく、メモリが許す限りどれだけ大きな整数でも扱えます。

個数やインデックス、ループ回数、離散的なカウントなど、誤差が許されない場面に適します。

Python
# 任意精度整数の例:非常に大きな数の桁数を確認
n = 10 ** 100  # 1の後ろに0が100個
print("桁数:", len(str(n)))
print("末尾10桁:", str(n)[-10:])  # 表示確認のため末尾だけを見る
実行結果
桁数: 101
末尾10桁: 0000000000

典型用途の例として、組み合わせや階乗、ハッシュ計算などで大きな整数が自然に現れます。

intはオーバーフローしない一方、非常に大きくなると計算コストやメモリ使用量は増大します(後述)。

floatの特徴:倍精度浮動小数点(IEEE 754)と近似表現

Pythonのfloatは通常、C言語のdoubleに相当し、IEEE 754の倍精度浮動小数点で実装されています。

有限のビット長で連続量を近似するため、ほとんどの小数は「ぴったり」ではなく「近い値」で表現されます。

Python
# 浮動小数点の分解能(機械イプシロン)を確認
import sys
print(sys.float_info.epsilon)  # 1.0に足しても1.0と区別できる最小の値
実行結果
2.220446049250313e-16

この近似性が、0.1+0.2が厳密には0.3と等しくならないといった誤差の源になります(後述)。

Pythonでの型確認・作成方法とリテラル(10, 1_000, 1.5, 1e-3 など)

type()isinstance()で型を確認できます。

数値リテラルは読みやすさのための桁区切り(_)や指数表記(e/E)が使えます。

Python
a = 10          # int
b = 1_000       # int(桁区切り)
c = 1.5         # float(小数点)
d = 1e-3        # float(指数表記、0.001)
print(type(a), type(b), type(c), type(d))

# 進数リテラルや文字列からの生成
e = 0b1010      # 2進数 -> 10
f = 0o12        # 8進数 -> 10
g = 0xA         # 16進数 -> 10
h = int("FF", 16)  # 文字列16進をintに
print(e, f, g, h)
実行結果
<class 'int'> <class 'int'> <class 'float'> <class 'float'>
10 10 10 255

intとfloatの違い・使い分けの基準

使い分けの判断基準:個数・離散値はint、測定値・連続量はfloat

  • 個数やインデックス、ID、ループ回数、ビット演算など、離散的で誤差が許されない値はintにします。
  • 長さ・時間・質量・緯度経度など連続量や測定値はfloatが自然です(ただし誤差を意識します)。

日付や時刻はdatetime、IDは文字列の方が適切な場合もあります。

数値で表せるからといって常にintfloatにするのではなく、意味的な型を選ぶのが安全です。

金額など正確な小数はDecimal、比率はFractionの検討

金額や税率など、桁や丸め規則を厳密に守る必要があるときはdecimal.Decimalが適しています。

有理数の比率計算はfractions.Fractionで誤差なく扱えます(詳細は後述)。

Python
from decimal import Decimal
from fractions import Fraction

price = Decimal("19.99")
tax_rate = Decimal("0.1")  # 10%
ratio = Fraction(2, 3)

print(price * 3)              # 正確
print(ratio + Fraction(1, 6)) # 2/3 + 1/6 = 5/6
実行結果
59.97
5/6

パフォーマンス・メモリの観点と大きなintの計算コスト

intは値が大きくなるほど内部の「桁」(ワード)数が増え、加減算・乗算・除算のコストやメモリ使用量が増えます。

一方でfloatは常に固定サイズです(CPythonでは通常8バイトのC doubleに相当します)。

以下はメモリ消費の一例です(実際の数値は環境により異なります)。

Python
import sys
small_int = 0
big_int = 10 ** 1000
flt = 0.0

print("small int:", sys.getsizeof(small_int))
print("big int  :", sys.getsizeof(big_int))
print("float    :", sys.getsizeof(flt))
実行結果
small int: 28
big int  : 160
float    : 24

大きなintのべき乗や大きな配列での保持は時間・メモリの面で重くなるため、アルゴリズムやデータ型の選択に注意が必要です。

計算方法の基本:演算子と挙動の違い

加減乗除・べき乗:+ – * / ** の結果型と典型パターン

  • + - *は、両辺がintならint、どちらかがfloatならfloatになります。
  • /は常に真の除算でfloatを返します(両辺がintでもfloat)。
  • **は整数同士ならint(巨大になる可能性)、floatが含まれればfloatです。pow(a, b, mod)の3引数形式は高速な整数の冪余を返します。
Python
print(2 + 3, type(2 + 3))
print(2 * 3.0, type(2 * 3.0))
print(5 / 2, type(5 / 2))          # float
print(2 ** 10, type(2 ** 10))      # int
print(pow(2, 10, 1000))            # 1024 mod 1000
実行結果
5 <class 'int'>
6.0 <class 'float'>
2.5 <class 'float'>
1024 <class 'int'>
24

/ と // と % の違い:真の除算、切り捨て除算、剰余(負数の挙動に注意)

  • /は真の除算(浮動小数点)。
  • //は床関数に基づく切り捨て除算(負無限大方向への丸め)。
  • %は剰余で、常にa == (a // b) * b + (a % b)を満たし、剰余の符号は除数bに一致します。
Python
print(7 / 3, 7 // 3, 7 % 3)       # 2.333..., 2, 1
print(-7 / 3, -7 // 3, -7 % 3)    # -2.333..., -3, 2
print(7 / -3, 7 // -3, 7 % -3)    # -2.333..., -3, -2
実行結果
2.3333333333333335 2 1
-2.3333333333333335 -3 2
-2.3333333333333335 -3 -2

丸めと小数点操作:round、math.floor、math.ceil、math.trunc の使い分け

  • round(x, ndigits)は銀行家の丸め(偶数丸め)。ndigits省略時は最も近い整数に丸めてintを返します。
  • math.floor(x)は床(小さい方向へ切り捨て)、math.ceil(x)は天井(大きい方向へ切り上げ)。
  • math.trunc(x)はゼロ方向への切り捨て。
Python
import math

print(round(2.5), round(3.5))               # 偶数丸め -> 2, 4
print(round(2.675, 2))                      # 二進表現の影響で 2.67
print(math.floor(-2.3), math.ceil(-2.3))    # -3, -2
print(math.trunc(-2.9))                     # -2(ゼロ方向)
実行結果
2 4
2.67
-3 -2
-2

型変換と比較のコツ【型変換と精度の注意点】

型変換:int()・float()・str()・文字列からの数値化(小数点の扱い)

int()は整数文字列を、float()は小数も含めて変換します。

int("10")は成功しますが、int("10.0")はエラーです(小数点は不可)。

Python
def safe_int(s: str):
    try:
        return int(s)
    except ValueError as e:
        return f"ValueError: {e}"

print(int(3.9))              # 小数からのintはゼロ方向切り捨て -> 3
print(float("1e-3"))         # 0.001
print(safe_int("10"))
print(safe_int("10.0"))      # エラー例
print(str(123), str(3.14))   # 数値 -> 文字列
実行結果
3
0.001
10
ValueError: invalid literal for int() with base 10: '10.0'
123 3.14

進数指定のint("FF", 16)のように基数も指定できます。

float("nan")float("inf")も作れます(後述の注意点参照)。

浮動小数点の安全な比較:math.isclose と相対誤差・絶対誤差

floatの直接比較は誤差のため危険です。

math.isclose(a, b, rel_tol, abs_tol)で相対誤差と絶対誤差の許容範囲を指定して比較します。

Python
import math
a = 0.1 + 0.2
print(a == 0.3)                                        # しばしばFalse
print(math.isclose(a, 0.3, rel_tol=1e-9, abs_tol=0.0)) # 許容誤差内でTrue
実行結果
False
True

大きさがゼロ付近の値を比較する場合はabs_tolを適切に設定することが重要です。

特殊値の扱い:NaN・Infinity の検出と比較の落とし穴

NaN(非数)はどの値とも等しくありません(自分自身とも)。

math.isnanmath.isinfmath.isfiniteで判定します。

Python
import math
x = float("nan")
y = float("inf")
z = -float("inf")

print(x == x, math.isnan(x))          # NaNは自分とも等しくない
print(y > 1e308, math.isinf(y))       # 無限大
print(math.isfinite(1.23), math.isfinite(y))
実行結果
False True
True True
True False

NaNを含む計算は結果がNaNに伝播しやすいため、入力データ検証で早めに除去・置換しましょう。

精度と誤差の注意点【floatの落とし穴】

0.1 + 0.2 ≠ 0.3 の理由:二進小数と丸め誤差

10進で有限桁の0.1は二進では循環小数となり、有限ビットでは表現しきれません。

最も近い近似値で表現するため誤差が出ます。

Python
s = 0.1 + 0.2
print("repr:", repr(s))
print("17桁表示:", format(s, ".17f"))
print("0.3の17桁:", format(0.3, ".17f"))
実行結果
repr: 0.30000000000000004
17桁表示: 0.30000000000000004
0.3の17桁: 0.29999999999999999

等価性比較ではなく、前述のmath.iscloseなどを用いるのが安全です。

金額計算はDecimal:コンテキスト、量子化(quantize)、丸めモード

decimal.Decimalは10進演算で誤差の管理が容易です。

getcontext()で精度や丸めモードを設定し、quantizeで桁数を揃えます。

Python
from decimal import Decimal, getcontext, ROUND_HALF_UP, ROUND_FLOOR

getcontext().prec = 28  # 演算精度(有効桁数)
price = Decimal("19.99")
qty = Decimal("3")
subtotal = price * qty              # 正確に59.97
tax_rate = Decimal("0.10")
tax = (subtotal * tax_rate).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
total = (subtotal + tax).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

print("小計:", subtotal)
print("税額:", tax)
print("合計:", total)

# 端数処理の違い(切り捨て)
v = Decimal("1.005")
print("四捨五入:", v.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP))
print("切り捨て :", v.quantize(Decimal("0.01"), rounding=ROUND_FLOOR))
実行結果
小計: 59.97
税額: 6.00
合計: 65.97
四捨五入: 1.01
切り捨て : 1.00

通貨単位ごとの規則(例:JPYは小数なし)に合わせて量子化の桁を変えます。

分数の厳密計算はFraction:比率・有理数の活用

fractions.Fractionは有理数を既約分数として正確に扱います。

文字列から生成すれば10進小数も正確に有理数化できます。

Python
from fractions import Fraction

print(Fraction(1, 3) * 6)                         # 2
print(Fraction("0.1") + Fraction("0.2") == Fraction("0.3"))  # True(正確)
print(Fraction(0.1))                               # 浮動小数点からは近似分数
print(Fraction(0.1).limit_denominator())           # 近い分数に制限
実行結果
2
True
3602879701896397/36028797018963968
1/10

Fraction(0.1)は二進表現由来の巨大分母になります。

必要に応じてFraction("0.1")limit_denominator()を使います。

表示フォーマットと実用Tips

表示の整形:f-string/format で小数点桁数・千位区切り・指数表記

f文字列やstr.formatのフォーマット指定で見やすく表示できます。

Python
n = 1234567
x = 1234.56789

print(f"{n:,}")         # 千位区切り
print(f"{x:.2f}")       # 小数2桁
print(f"{x:,.3f}")      # 千位区切り + 小数3桁
print(f"{x:.2e}")       # 指数表記
print(f"{0.125:.3%}")   # パーセント
実行結果
1,234,567
1234.57
1,234.568
1.23e+03
12.500%

金額はDecimalのままフォーマットするのが安全です。

桁あふれや丸めのタイミングに注意します。

科学技術計算のfloat精度とNumPyでのdtype(float32/float64)

数値計算ライブラリNumPyではdtypeで精度を選べます。

float64が標準で、float32はメモリを節約できますが精度は劣ります。

NumPyインストールコマンド
pip install numpy
Python
import numpy as np

a32 = np.array([0.1, 0.2, 0.3], dtype=np.float32)
a64 = np.array([0.1, 0.2, 0.3], dtype=np.float64)

print(a32.dtype, a64.dtype)
print(a32.sum(), a64.sum())  # 近いが等しくないことがある
print(a32.sum() == np.float32(0.6), np.isclose(a32.sum(), np.float32(0.6)))
print(a64.sum() == np.float64(0.6), np.isclose(a64.sum(), np.float64(0.6)))
実行結果
float32 float64
0.6000001 0.6
False True
False True

シミュレーションや学習ではfloat32で十分なこともありますが、感度の高い統計量や安定性重視の線形代数ではfloat64を選ぶのが無難です。

比較はnp.isclose/np.allcloseを使います。

よくある落とし穴まとめ:整数除算の結果型、負の剰余、intはオーバーフローしないが遅くなる

  • 5 / 22.5float)になります。整数結果が欲しければ//divmodを使います。
  • 負数の//は床方向に丸めるため、-7 // 3 == -3です。%の符号は除数と同じになります。
  • intはオーバーフローしない代わりに大きくなるほど遅くなります。桁数が巨大になる計算はアルゴリズムや表現(モジュラ演算、対数領域など)を検討しましょう。

まとめ

Pythonのintは誤差なく離散値を扱える任意精度整数、floatは連続量を高速に近似できる倍精度浮動小数点です。

用途に応じて適切に使い分け、計算では///、丸め関数の違い、負数の剰余挙動を正しく理解することが重要です。

floatの比較はmath.iscloseを用い、金額はDecimal、比率はFractionの活用を検討してください。

表示はフォーマット指定で見やすく整え、科学技術計算ではNumPyのdtypeを目的に合わせて選択します。

型と丸め・誤差の基礎を押さえれば、数値計算の信頼性と保守性は大きく向上します。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!