Pythonでは文字列から数値へ、あるいは数値から文字列へと柔軟に変換できます。
本記事では、int・float・strといった基本関数から、基数(2進・16進)変換、フォーマット指定、エラー処理、ロケールや全角文字の注意点まで、実務で迷わないためのコツとサンプルコードを体系的に解説します。
Pythonで文字列と数値を相互変換する基本(int・float・str)
Pythonで文字列⇄数値を変換する場面と選ぶべき型(int・float・str)
文字列と数値の相互変換は、ユーザー入力、CSV/JSONなどの外部データの読み書き、ログ整形、数値演算結果の表示などで頻出します。
選ぶべき型は目的により異なります。
整数演算にはint、小数を含む実数にはfloat、桁落ちや通貨計算など誤差が許されない領域ではdecimal.Decimalが有力な選択肢です。
人に見せるための文字列化はstr(あるいは書式指定)、デバッグ時の正確な表現にはreprが役立ちます。
- int: 符号付き整数。2進/8進/16進など基数変換対応。
- float: 倍精度浮動小数点。高速だが丸め誤差あり。
- decimal.Decimal: 10進演算で正確性重視(金融など)。
- str: ユーザー向けの可読表現。
- repr: 開発者向けの正確な再現可能表現(目安)。
文字列→数値に変換する方法(Pythonのint・float)
int()の使い方と基数(base)指定:2進・8進・16進の文字列を整数に変換
int()
はデフォルト10進として文字列を整数に変換します。
第2引数base
で2〜36の基数指定が可能です。
前後の空白や改行、先頭の+
/-
は許容されます。
# 10進(デフォルト)
print(int("42")) # 42
print(int(" -7\n")) # -7
# 2進・8進・16進(base 指定)
print(int("1010", 2)) # 2進 => 10
print(int("755", 8)) # 8進 => 493
print(int("ff", 16)) # 16進 => 255
# 0x/0o/0b プレフィックス付きでも base を合わせれば解釈可
print(int("0xff", 16)) # 255
print(int("0b1011", 2)) # 11
# 自動検出(0x/0o/0b を解釈): base=0 を使う
print(int("0b1001", 0)) # 9
print(int("0o17", 0)) # 15
print(int("0x1A", 0)) # 26
42
-7
10
493
255
255
11
9
15
26
float()の使い方:小数・指数表記の文字列をfloatに変換
float()
は小数点や指数表記(e/E)を含む文字列を浮動小数点に変換します。
print(float("3.14159"))
print(float("-2.5"))
print(float("6.022e23")) # 科学(指数)表記
print(float("1e-3"))
3.14159
-2.5
6.022e+23
0.001
指数表記は人間には便利ですが、表示時に意図せずe
表記になることがあるため、後述のフォーマット指定で制御すると安心です。
前処理のコツ:strip()・replace()で空白やカンマを除去
外部データには空白やカンマ区切りが含まれることが多いです。
安全に変換するには簡単な前処理を行います。
def to_number_clean(s: str) -> float:
"""空白/改行/カンマを除去して float に変換する簡易関数"""
cleaned = s.strip().replace(",", "")
return float(cleaned)
print(to_number_clean(" 1,234.50 \n"))
1234.5
通貨記号や全角スペースが混じる場合は正規表現やstr.translate
/unicodedata.normalize
での正規化が有効です(後述の全角・ロケール参照)。
数字判定の違い:str.isdigit・isdecimal・isnumericの使い分け
文字が「数字か」を判定するメソッドには微妙な違いがあります。
代表的な違いを整理します。
- isdecimal: 10進数字(0〜9)のみ。最も厳格。
- isdigit: 上記に加え、上付き/下付き数字などもTrue。
- isnumeric: さらにローマ数字や全角数字、分数表現など数値的に解釈可能なものまで含む。
例と差分:
samples = ["123", "123", "Ⅳ", "²", "三", "-123"]
for s in samples:
print(s, {
"isdecimal": s.isdecimal(),
"isdigit": s.isdigit(),
"isnumeric": s.isnumeric(),
})
123 {'isdecimal': True, 'isdigit': True, 'isnumeric': True}
123 {'isdecimal': True, 'isdigit': True, 'isnumeric': True}
Ⅳ {'isdecimal': False, 'isdigit': False, 'isnumeric': True}
² {'isdecimal': False, 'isdigit': True, 'isnumeric': True}
三 {'isdecimal': False, 'isdigit': False, 'isnumeric': True}
-123 {'isdecimal': False, 'isdigit': False, 'isnumeric': False}
判定系は符号や小数点を考慮しないため、実用上は「クリーニングしてからint/floatで変換し、ダメなら例外処理」が堅実です。
エラー対策:try/exceptでValueErrorを安全に処理
文字列変換は失敗し得ます。
ValueError
やTypeError
を握り、入力の検証・ログ出力を行いましょう。
def safe_int(s, base=10, default=None):
"""int 変換の安全版。失敗時は default を返す"""
try:
return int(s, base)
except (ValueError, TypeError):
return default
print(safe_int("42")) # 42
print(safe_int("not a number")) # None
print(safe_int(None)) # None
42
None
None
全角数字・マイナス記号・ロケールの注意点
現実のデータには全角数字(123)、全角マイナス(−: U+2212)、全角スペースなどが混在します。
unicodedata.normalize("NFKC", s)
で「互換分解→合成」することで半角に寄せられる場合が多いです。
ただし全角マイナスはNFKCでASCIIのハイフンに変わらないことがあり、別途置換が必要です。
import unicodedata
def normalize_number_string(s: str) -> str:
# 互換正規化で数字や記号を半角寄りに
t = unicodedata.normalize("NFKC", s)
# Unicode のマイナス(U+2212)を ASCII ハイフンに揃える
t = t.replace("\u2212", "-")
# よくある不可視スペースの除去(必要に応じて拡張)
t = t.replace("\u00A0", " ").strip()
return t
raw = " -1234.56" # 全角スペース/全角マイナス/全角数字/全角ドット
norm = normalize_number_string(raw)
print(raw, "=>", norm, float(norm))
-1234.56 => -1234.56 -1234.56
ロケールにより小数点がコンマの文化圏(例: “1.234,56”)では、locale
やbabel
の活用を検討してください(後述)。
数値→文字列に変換する方法(Pythonのstr・format)
str()とrepr()の違いと使い分け
str(x)
は人に見せるための簡潔な表現、repr(x)
は開発者向けの正確な表現(可能なら再評価可能)を返します。
floatではreprの方が内部値に忠実です。
x = 1/10 + 2/10 + 3/10 # 浮動小数の誤差例
print("str:", str(x))
print("repr:", repr(x))
from decimal import Decimal
d = Decimal("0.1") + Decimal("0.2") + Decimal("0.3")
print("Decimal str:", str(d))
print("Decimal repr:", repr(d))
str: 0.6000000000000001
repr: 0.6000000000000001
Decimal str: 0.6
Decimal repr: Decimal('0.6')
ユーザー向け表示はstr
や書式指定、デバッグや差分調査にはrepr
が有用です。
f文字列(f-string)とformat()の基本
f文字列は可読性と性能に優れ、式の埋め込みやフォーマット指定が直感的です。
str.format()
も等価の書式指定が可能です。
name = "Alice"
score = 93.456
print(f"{name} のスコアは {score:.1f} 点")
print("{} のスコアは {:.1f} 点".format(name, score))
Alice のスコアは 93.5 点
Alice のスコアは 93.5 点
フォーマット指定子:小数点桁数、ゼロ埋め、千区切りの設定
主要な指定子の例を示します。
n = 42
pi = 3.1415926535
big = 1234567
# ゼロ埋め・幅指定
print(f"{n:05d}") # 00042
# 固定小数点・桁数
print(f"{pi:.3f}") # 3.142
# 千区切り
print(f"{big:,}") # 1,234,567
# 左寄せ/右寄せ/中央寄せ
print(f"[{n:<5d}] [{n:>5d}] [{n:^5d}]")
00042
3.142
1,234,567
[42 ] [ 42] [ 42 ]
科学表記(指数表記)の制御:e表記を避ける/使う
指数表記を強制するにはe
/E
、避けたい場合はf
やf
+精度指定を使います。
g
は状況に応じて固定/指数を自動選択します。
x = 123456789.0
y = 0.000012345
print(f"{x:e}") # 1.234568e+08
print(f"{x:.0f}") # 123456789
print(f"{y:f}") # 0.000012
print(f"{y:.8f}") # 0.00001235 (丸め)
print(f"{y:.8g}") # 1.2345e-05(gは自動)
1.234568e+08
123456789
0.000012
0.00001235
1.2345e-05
非常に大きい/小さい値で指数表記を避けたいとき、表示桁数を十分に確保するか、Decimalの利用を検討します。
高精度が必要な場合のDecimalの文字列化
decimal.Decimal
は10進小数での正確な演算が可能です。
quantize
で桁数と丸めを制御できます。
from decimal import Decimal, getcontext, ROUND_HALF_UP
getcontext().prec = 28 # 演算精度(有効桁数)
amount = Decimal("1234.5675")
# 指定小数点以下2桁、四捨五入で丸め
rounded = amount.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(str(rounded)) # ユーザー表示
print(f"{rounded:,.2f}") # 千区切りつき
print(repr(rounded)) # 正確な表現
1234.57
1,234.57
Decimal('1234.57')
基数変換・進数表現の相互変換(10進⇄2進・8進・16進)
文字列→数値:int(s, base)で任意基数の文字列を整数に
int(s, base)
で2〜36の任意基数から10進のintへ変換できます。
基数36では英字a〜zが追加で使用可能です。
print(int("z", 36)) # 35
print(int("1z", 36)) # 71
print(int("101101", 2)) # 45
35
71
45
数値→文字列:bin()・oct()・hex()・format()の使い方
整数からの進数文字列化は組み込み関数やformat
で行えます。
n = 255
print(bin(n)) # '0b11111111'
print(oct(n)) # '0o377'
print(hex(n)) # '0xff'
# プレフィックスなし、桁幅・ゼロ埋め
print(format(n, "b")) # '11111111'
print(format(n, "08b")) # '11111111'(8桁)
print(format(n, "#06x"))# '0x00ff'(#で接頭辞、幅6、ゼロ埋め)
print(format(n, "X")) # 'FF'(大文字)
0b11111111
0o377
0xff
11111111
11111111
0x00ff
FF
0b/0o/0xプレフィックスと大小文字(A-F)の扱い
bin/oct/hex
はそれぞれ0b
/0o
/0x
の接頭辞つきで小文字表現を返します。- 書式指定
#b/#o/#x
で接頭辞を含め、X
を使うと16進のA〜Fが大文字になります。 - 入力時は
int(s, 0)
で接頭辞の自動解釈が便利です。
よくあるエラー・落とし穴と対処法
ValueError・TypeErrorの原因とデバッグのポイント
- ValueError: 数字でない文字、余計な記号、空文字、基数に不正な文字を含む場合に発生します。例:
int("12,34")
,int("g", 16)
,float("")
。 - TypeError:
None
や非文字列・非数値を渡した場合など。例:int(None)
。
対処として、入力の事前バリデーション、正規化(空白・カンマ・全角の処理)、try/except
でのフォールバック、エラー時の原文ログ保持を行います。
空文字・None・NaN/infの扱い(float(‘nan’)・float(‘inf’))
空文字やNoneは適切に弾く必要があります。
float("NaN")
やfloat("inf")
は特殊値を返しますが、比較や合計時の扱いに注意します。
import math
vals = ["", None, "NaN", "inf", "-inf", "1.0"]
parsed = []
for v in vals:
try:
parsed.append(float(v))
except (TypeError, ValueError):
parsed.append(None)
print(parsed)
print([math.isnan(x) if isinstance(x, float) else None for x in parsed])
print([math.isinf(x) if isinstance(x, float) else None for x in parsed])
[None, None, nan, inf, -inf, 1.0]
[None, None, True, False, False, False]
[None, None, False, True, True, False]
NaNはどの値とも等しくない(NaN != NaN)ため、math.isnan()
で判定します。
浮動小数点の丸め誤差とDecimal検討の目安
floatは2進表現のため、10進で有限桁の値でも誤差が生じます。
金額・在庫など桁落ちが問題になるケースや法令/契約で丸め規則が定義される領域ではDecimalを用い、丸め規則(ROUND_HALF_UP等)を明示します。
単なる表示用途で「見た目の丸め」が必要ならformat
で十分です。
ロケール依存の区切り文字・小数点(, と .)への対応
ドイツ語圏などでは小数点が,
、千区切りが.
となります。
locale
を設定するか、babel
を使ってパース/フォーマットします。
pip install Babel
# locale を使った例(OSにロケールがインストールされている必要あり)
import locale
locale.setlocale(locale.LC_ALL, "de_DE.UTF-8") # 例: ドイツ
print(locale.atof("1.234,56")) # 1234.56
# Babel を使った例(pip install babel)
from babel.numbers import parse_decimal, format_decimal
x = parse_decimal("1.234,56", locale="de_DE")
print(x) # Decimal('1234.56')
print(format_decimal(x, locale="de_DE")) # '1.234,56'
1234.56
1234.56
1.234,56
実運用では、入力フォーマットを固定(例: 常に.
を小数点、,
は無視)するか、ロケールを明示的に適用するのが安全です。
使えるサンプルコード集(コピペ可)
金額文字列”1,234.56″を数値に変換して合計する
カンマ付き金額の配列を正規化して合計します。
小数誤差を避けるためDecimalを使用します。
from decimal import Decimal, ROUND_HALF_UP
def parse_money(s: str) -> Decimal:
# 通貨記号や空白に頑健な最小限の前処理(必要なら拡張)
t = s.strip().replace(",", "")
return Decimal(t)
items = ["1,234.56", "200", "99.44", "0.00"]
total = sum(parse_money(x) for x in items)
# 2桁で四捨五入して表示
total_disp = total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(f"合計: {total_disp:,.2f}")
合計: 1,534.00
ユーザー入力を安全にint/floatに変換するユーティリティ関数
前処理・正規化・例外処理を含む安全な変換ヘルパです。
import unicodedata
from typing import Optional, Union
def normalize_numeric_text(s: str) -> str:
t = unicodedata.normalize("NFKC", s)
t = t.replace("\u2212", "-") # Unicode マイナスをASCIIに
t = t.replace(",", "") # カンマ削除(必要ならロケール対応へ)
return t.strip()
def to_int(s: Union[str, int, float, None], default: Optional[int]=None) -> Optional[int]:
if s is None:
return default
if isinstance(s, int):
return s
if isinstance(s, float):
# float を int にする場合は明示的に丸め規則を決める
return int(s)
try:
t = normalize_numeric_text(str(s))
return int(t, 10)
except ValueError:
return default
def to_float(s: Union[str, int, float, None], default: Optional[float]=None) -> Optional[float]:
if s is None:
return default
if isinstance(s, (int, float)):
return float(s)
try:
t = normalize_numeric_text(str(s))
return float(t)
except ValueError:
return default
print(to_int(" -1,23 ")) # -123
print(to_float(" 1,234.50 ")) # 1234.5
print(to_int("not number", 0)) # 0
-123
1234.5
0
2進・16進の文字列を数値に、数値を進数文字列に変換する方法
入出力の両方向を網羅したユーティリティです。
def parse_base(s: str, base: int) -> int:
# base=0 で 0b/0o/0x 接頭辞を自動解釈させるのも可
return int(s, base)
def to_base(n: int, base: int, prefix: bool = False, upper: bool = False) -> str:
if base == 2:
fmt = "#b" if prefix else "b"
elif base == 8:
fmt = "#o" if prefix else "o"
elif base == 16:
fmt = "#X" if (prefix and upper) else ("#x" if prefix else ("X" if upper else "x"))
else:
# 任意基数(2〜36)は format では直接不可。自作変換で対応する
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" if upper else "0123456789abcdefghijklmnopqrstuvwxyz"
if n == 0:
return "0"
neg = n < 0
n = abs(n)
out = []
while n:
n, r = divmod(n, base)
out.append(digits[r])
s = "".join(reversed(out))
return ("-" if neg else "") + s
return format(n, fmt)
# 使い方例
print(parse_base("0xff", 16)) # 255
print(parse_base("1010", 2)) # 10
print(to_base(255, 2, prefix=True)) # 0b11111111
print(to_base(255, 16, prefix=True, upper=True)) # 0xFF
print(to_base(71, 36, upper=True)) # 1Z
255
10
0b11111111
0xFF
1Z
数値を文字列に整形:桁区切り、固定小数点、ゼロ埋めのフォーマット例
よく使う整形パターンをまとめます。
n = 7
x = 1234.5
# ゼロ埋め(幅4)
print(f"{n:04d}") # 0007
# 固定小数点(小数2桁)
print(f"{x:.2f}") # 1234.50
# 千区切り
print(f"{x:,.2f}") # 1,234.50
# 左寄せ・埋め文字
print(f"{n:*<5d}") # 7****
# 負号の表記制御(常に符号)
print(f"{x:+.1f}") # +1234.5
print(f"{-x:+.1f}") # -1234.5
0007
1234.50
1,234.50
7****
+1234.5
-1234.5
まとめ
Pythonの文字列⇄数値変換は、int・float・strといった基本に加え、基数指定、書式指定、例外処理、Unicode正規化、ロケール対応まで押さえると実務で強力に機能します。
変換前には不要な空白やカンマ、全角記号を正規化し、失敗時はtry/exceptで安全に処理しましょう。
表示はf文字列やformatの指定子で要件どおりに整形し、金額や高精度が求められる場面ではDecimalを活用すると誤差や丸め規則をコントロールできます。
特殊値(NaN/inf)や指数表記の挙動、0b/0o/0xの接頭辞、16進の大小文字なども理解しておけば、文字列と数値の相互変換で迷うことはなくなるはずです。