Pythonでfloat型の数値を扱う際に、小数点以下の桁数が思い通りに表示されず困った経験がある方は多いです。計算結果をレポートやログに出力する場面では、桁数を正確に制御することが求められます。
float型の桁数制御にはf-stringやformat()による表示の書式指定だけではなく、round()による丸めやDecimalモジュールによる高精度計算など、用途に応じた複数の方法があります。目的に合わない方法を選ぶと、表示のずれや計算誤差の原因になるため、それぞれの違いを正しく理解することが重要です。
この記事では、Pythonでfloat型の小数点以下の桁数を指定・丸め・取得する方法を、サンプルコード付きで解説していきます。
目次
- Pythonでfloat型の小数点以下の桁数を指定する方法
- f-stringで小数点以下の桁数を指定する
- format()メソッドで小数点以下の桁数を指定する
- %演算子で小数点以下の桁数を指定する
- Pythonでfloat型の小数点以下の桁数を丸める方法
- round()関数で指定桁に丸める(偶数丸め)
- math.floor()で小数点以下を切り捨てる
- math.ceil()で小数点以下を切り上げる
- PythonのDecimalモジュールでfloat型の桁数を正確に制御する方法
- Decimalで小数点以下の桁数を指定する
- floatの浮動小数点誤差をDecimalで回避する
- Pythonでfloat型の桁数を取得する方法
- 文字列変換とlen()で桁数を取得する
- Decimalで小数点以下の桁数を取得する
- Pythonのfloat型の桁数に関するよくある質問
- round()で四捨五入すると結果がずれるのはなぜですか?
- f-stringとformat()はどちらを使うべきですか?
- floatの有効桁数は何桁ですか?
Pythonでfloat型の小数点以下の桁数を指定する方法
Pythonでfloat型の値を出力する際、小数点以下の桁数を指定するには書式指定を使います。書式指定とは、文字列の中で数値の表示形式をフォーマット文字列で制御する仕組みのことです。
桁数を指定する方法として、以下の3つがあります。
- f-stringで小数点以下の桁数を指定する
- format()メソッドで小数点以下の桁数を指定する
- %演算子で小数点以下の桁数を指定する
それぞれ書式の記法は異なりますが、いずれも「:.Nf」のようなフォーマット指定子で小数点以下N桁まで表示する点は共通しています。用途や好みに応じて使い分けてください。
それでは各方法について、サンプルコード付きで解説していきます。
f-stringで小数点以下の桁数を指定する
f-stringはPython 3.6以降で使える文字列フォーマット機能で、変数を波括弧 {} の中に直接記述できます。小数点以下の桁数を指定するには、コロンの後に「.Nf」と記述し、Nに表示したい桁数を指定します。
value = 3.14159265
# 小数点以下2桁で表示
print(f"{value:.2f}") # 3.14
# 小数点以下4桁で表示
print(f"{value:.4f}") # 3.1416
# 小数点以下0桁(整数部分のみ)で表示
print(f"{value:.0f}") # 3
上記のコードでは、f-stringの波括弧内に「:.2f」のように書式指定子を記述しています。「.2f」の「2」が小数点以下の桁数を意味し、「f」は固定小数点表記を表すフォーマット型指定文字です。
指定した桁数より元の数値の桁数が多い場合は丸められるため、「:.4f」を指定すると3.14159265が3.1416と表示されます。この丸め処理はPythonの偶数丸め(銀行家の丸め)に従うため、一般的な四捨五入とは結果が異なる場合があります。
逆に桁数が少ない場合はゼロで埋められるため、「:.4f」に対して3.14を渡すと3.1400と表示されます。
format()メソッドで小数点以下の桁数を指定する
format()メソッドは文字列の置換フィールド {} を使って値をフォーマットする方法で、Python 3.0以降で利用できます。f-stringと同じ書式指定子「:.Nf」を波括弧の中に記述することによって、小数点以下の桁数を制御できます。
value = 3.14159265
# 小数点以下2桁で表示
print("{:.2f}".format(value)) # 3.14
# 小数点以下4桁で表示
print("{:.4f}".format(value)) # 3.1416
# 複数の値を同時にフォーマット
a, b = 1.23456, 7.89012
print("{:.2f}, {:.3f}".format(a, b)) # 1.23, 7.890
上記のコードでは、文字列中の置換フィールド {} に「:.2f」や「:.4f」を記述し、format()メソッドの引数に対象の数値を渡しています。複数の値を同時にフォーマットする場合は、置換フィールドを複数並べてformat()の引数にそれぞれの値を渡します。
format()メソッドはフォーマット文字列を変数として動的に構成したい場合に有用です。新しいコードではf-stringの方が簡潔に書けるため、Python 3.6以降の環境ではf-stringの使用を推奨します。
%演算子で小数点以下の桁数を指定する
%演算子はC言語のprintf関数に由来する古い書式指定方法で、Pythonの初期バージョンから利用できます。小数点以下の桁数を指定するには「%.Nf」と記述し、Nに表示したい桁数を指定します。
value = 3.14159265
# 小数点以下2桁で表示
print("%.2f" % value) # 3.14
# 小数点以下4桁で表示
print("%.4f" % value) # 3.1416
# 複数の値を同時にフォーマット
a, b = 1.23456, 7.89012
print("%.2f, %.3f" % (a, b)) # 1.23, 7.890
上記のコードでは、文字列中に「%.2f」のような書式指定子を記述し、%演算子の右側に対象の数値を渡しています。複数の値をフォーマットする場合はタプルで渡す必要があるため、(a, b)のように括弧で囲みます。
%演算子はPython公式ドキュメントで「旧式の書式指定」と位置づけられており、新規コードではf-stringやformat()メソッドの使用が推奨されています。既存コードのメンテナンスや古いPythonバージョンとの互換性が求められる場合を除き、新規コードではf-stringやformat()の使用を検討してください。
Pythonでfloat型の小数点以下の桁数を丸める方法
前のセクションではfloat型の「表示桁数」を制御する方法を紹介しましたが、ここでは数値そのものを特定の桁数に丸める方法を解説します。表示の桁数指定は見た目だけを変えるのに対し、丸め処理は変数に格納される値自体が変化する点が異なります。
小数点以下の桁数を丸める方法として、以下の3つがあります。
- round()関数で指定桁に丸める(偶数丸め)
- math.floor()で小数点以下を切り捨てる
- math.ceil()で小数点以下を切り上げる
それぞれ丸めの方向が異なるため、用途に応じて適切な関数を選択してください。金額計算や統計処理など、丸め方向が結果に影響する場面では特に注意が必要です。
それでは各方法について、解説していきます。
round()関数で指定桁に丸める(偶数丸め)
round()関数はPythonの組み込み関数で、数値を指定した桁数に丸めます。一般的な四捨五入ではなく「偶数丸め(銀行家の丸め)」を採用しており、値がちょうど中間の場合は最も近い偶数に丸められます。
第1引数に対象の数値、第2引数に小数点以下の桁数を指定することによって、任意の桁で丸めることができます。
value = 3.14159265
# 小数点以下2桁に丸める
result1 = round(value, 2)
print(result1) # 3.14
# 小数点以下4桁に丸める
result2 = round(value, 4)
print(result2) # 3.1416
# 小数点以下0桁(整数に丸める)
result3 = round(value, 0)
print(result3) # 3.0
# 第2引数を省略すると整数を返す
result4 = round(value)
print(result4) # 3
print(type(result4)) # <class 'int'>
# 偶数丸めの挙動(中間値は最も近い偶数に丸められる)
print(round(2.5)) # 2
print(round(3.5)) # 4
# 浮動小数点の内部表現による影響
print(round(2.675, 2)) # 2.67(2.68ではない)
上記のコードでは、round()関数の第2引数で丸め先の桁数を指定しています。第2引数に0を渡すとfloat型の3.0が返されますが、第2引数を省略するとint型の3が返される点に注意してください。
round(2.5)が2になるのは偶数丸めの仕様によるものですが、round(2.675, 2)が2.68ではなく2.67になるのは浮動小数点の内部表現が原因です。2.675はfloatの2進数表現では2.675より僅かに小さい値になるため、丸め結果が直感と異なります。
一般的な四捨五入(0.5を常に切り上げ)を行いたい場合は、DecimalモジュールのROUND_HALF_UPを使用してください。
math.floor()で小数点以下を切り捨てる
math.floor()関数はmathモジュールに含まれる関数で、数値を負の無限大方向に切り捨てます。正の数では小数部分を取り除いたように見えますが、負の数では-3.1が-4になるように、より小さい整数に丸められる点に注意が必要です。
import math
value1 = 3.999
value2 = -3.1
# 正の数の切り捨て
print(math.floor(value1)) # 3
# 負の数の切り捨て(負の無限大方向に丸める)
print(math.floor(value2)) # -4
# 任意の桁で切り捨てる場合は10のべき乗と組み合わせる
value3 = 3.14159
digits = 2
result = math.floor(value3 * 10 ** digits) / 10 ** digits
print(result) # 3.14
上記のコードでは、math.floor()を使って小数点以下を切り捨てています。math.floor()は整数への切り捨てのみを行うため、任意の小数点以下の桁数で切り捨てたい場合は10のべき乗を掛けてから切り捨て、再度割り戻す方法を使います。
ただし、この方法は浮動小数点の誤差により意図しない結果になる場合があります(例: 2.55 * 100が255.0ではなく254.99...になるケース)。厳密な処理が必要な場面ではDecimalモジュールのROUND_FLOORを使用してください。
単純にゼロ方向へ切り捨てたい場合は、int()関数やmath.trunc()関数を使用します。
math.ceil()で小数点以下を切り上げる
math.ceil()関数はmathモジュールに含まれる関数で、数値を正の無限大方向に切り上げます。切り上げとは、小数点以下に値がある場合に整数部分を1つ大きくする処理のことです。
import math
value1 = 3.001
value2 = -3.9
# 正の数の切り上げ
print(math.ceil(value1)) # 4
# 負の数の切り上げ(正の無限大方向に丸める)
print(math.ceil(value2)) # -3
# 任意の桁で切り上げる場合は10のべき乗と組み合わせる
value3 = 3.14159
digits = 2
result = math.ceil(value3 * 10 ** digits) / 10 ** digits
print(result) # 3.15
上記のコードでは、math.ceil()を使って小数点以下を切り上げています。math.floor()と同様に、任意の小数点以下の桁数で切り上げたい場合は10のべき乗との組み合わせが必要です。
負の数に対してmath.ceil()を使うと、-3.9が-3になるように正の無限大方向に丸められます。正の数の端数処理で常に切り上げたい場合に使われますが、10のべき乗方式はmath.floor()と同様に浮動小数点の誤差の影響を受けます。
金額計算など高精度が必要な場面ではDecimalモジュールのROUND_CEILINGを使用してください。
PythonのDecimalモジュールでfloat型の桁数を正確に制御する方法
Pythonのfloat型はIEEE 754倍精度浮動小数点数で表現されるため、10進数で正確に表せない値が存在します。たとえば、0.1 + 0.2の結果は0.3ではなく0.30000000000000004になります。
このような浮動小数点誤差を回避し、小数点以下の桁数を正確に制御したい場合は、Decimalモジュールが有効です。Decimalモジュールとは、Python標準ライブラリに含まれる10進数の高精度演算を提供するモジュールのことです。
- Decimalで小数点以下の桁数を指定する
- floatの浮動小数点誤差をDecimalで回避する
それでは各方法について、解説していきます。
Decimalで小数点以下の桁数を指定する
Decimalオブジェクトのquantize()メソッドを使うと、小数点以下の桁数を正確に指定できます。quantize()メソッドとは、Decimalオブジェクトの精度を指定したDecimal値に合わせて丸めるメソッドのことです。
from decimal import Decimal, ROUND_HALF_UP, ROUND_DOWN
value = Decimal("3.14159265")
# 小数点以下2桁に四捨五入
result1 = value.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(result1) # 3.14
# 小数点以下4桁に四捨五入
result2 = value.quantize(Decimal("0.0001"), rounding=ROUND_HALF_UP)
print(result2) # 3.1416
# 小数点以下2桁に切り捨て
result3 = value.quantize(Decimal("0.01"), rounding=ROUND_DOWN)
print(result3) # 3.14
# 小数点以下0桁に四捨五入
result4 = value.quantize(Decimal("1"), rounding=ROUND_HALF_UP)
print(result4) # 3
上記のコードでは、quantize()の第1引数に目標の桁数を示すDecimalオブジェクト(「0.01」で小数点以下2桁)を渡し、rounding引数で丸めモードを指定しています。ROUND_HALF_UPは一般的な四捨五入、ROUND_DOWNは切り捨てを意味します。
quantize()のデフォルトの丸めモードはROUND_HALF_EVEN(偶数丸め)のため、一般的な四捨五入が必要な場合はrounding=ROUND_HALF_UPの明示が必須です。
Decimalオブジェクトを生成する際は、float型ではなく文字列で渡す点が重要です。Decimal(0.1)のようにfloatを直接渡すと、浮動小数点の内部表現がそのまま引き継がれるため、Decimal("0.1")のように文字列で渡してください。
floatの浮動小数点誤差をDecimalで回避する
float型では0.1 + 0.2が0.30000000000000004になるように、10進数の小数を2進数で正確に表現できないことが誤差の原因です。Decimalモジュールは10進数をそのまま扱うため、10進数で有限桁の小数を正確に表現できます。
ただし、1/3のような10進数でも無限小数になる除算では丸めが発生するため、あらゆる誤差を回避できるわけではありません。
from decimal import Decimal
# float型の計算(誤差が発生する)
float_result = 0.1 + 0.2
print(float_result) # 0.30000000000000004
print(float_result == 0.3) # False
# Decimal型の計算(誤差が発生しない)
decimal_result = Decimal("0.1") + Decimal("0.2")
print(decimal_result) # 0.3
print(decimal_result == Decimal("0.3")) # True
# 連続した計算で誤差が蓄積する例
float_sum = 0.1 + 0.1 + 0.1
decimal_sum = Decimal("0.1") + Decimal("0.1") + Decimal("0.1")
print(float_sum) # 0.30000000000000004
print(decimal_sum) # 0.3
上記のコードでは、float型とDecimal型の計算結果を比較しています。float型では0.1 + 0.2の結果が0.3と一致しませんが、Decimal型では正確に0.3になります。
Note that this is in the very nature of binary floating-point: this is not a bug in Python, and it is not a bug in your code either. You'll see the same kind of thing in all languages that support your hardware's floating-point arithmetic.
出典:Python公式ドキュメント - Floating-Point Arithmetic: Issues and Limitations
金額計算や会計処理など、10進数の小数を正確に扱う必要がある場面ではDecimalモジュールの使用を推奨します。ただし、Decimal型はfloat型と比較して演算速度が遅いため、大量の数値を高速に処理する場合はfloat型の方が適しています。
Pythonでfloat型の桁数を取得する方法
float型の値が持つ桁数を調べたい場面として、入力値のバリデーションや出力フォーマットの自動調整などがあります。Pythonにはfloat型の桁数を直接返す組み込み関数はありませんが、文字列変換やDecimalモジュールを使うことによって表示上の桁数を取得できます。
ここで取得できるのはstr()が返す10進表現の桁数であり、floatの内部精度(2進数53ビット)とは異なる点に注意してください。
- 文字列変換とlen()で桁数を取得する
- Decimalで小数点以下の桁数を取得する
それでは各方法について、解説していきます。
文字列変換とlen()で桁数を取得する
float型の値をstr()関数で文字列に変換し、小数点「.」で分割することによって、整数部分と小数部分の桁数をそれぞれ取得できます。str()関数とは、Pythonの組み込み関数で任意の値を文字列表現に変換する関数のことです。
value = 3.14159
# 文字列に変換して小数点で分割
str_value = str(value)
parts = str_value.split(".")
# 整数部分の桁数
integer_digits = len(parts[0])
print(f"整数部分の桁数: {integer_digits}") # 1
# 小数部分の桁数
decimal_digits = len(parts[1]) if len(parts) > 1 else 0
print(f"小数部分の桁数: {decimal_digits}") # 5
# 全体の桁数(小数点を除く)
total_digits = integer_digits + decimal_digits
print(f"全体の桁数: {total_digits}") # 6
上記のコードでは、str()でfloat値を文字列に変換し、split(".")で整数部分と小数部分に分割しています。len()関数で各部分の文字数を取得すれば、表示上の桁数を数えることができます。
ただし、これはfloatの内部精度や元の入力桁数ではなく、str()が返す最短の10進表現の文字数にすぎない点に注意してください。
この方法には制限があり、極端に小さい値(例: 0.00001)をstr()で変換すると「1e-05」のような指数表記になるため、split(".")による桁数取得が正しく機能しません。また、str(0.1 + 0.2)は「0.30000000000000004」になるように、演算結果では想定外の桁数が返される場合があります。
正確な桁数が必要な場合は、次のDecimalを使った方法を使用してください。
Decimalで小数点以下の桁数を取得する
Decimalオブジェクトのas_tuple()メソッドを使うと、数値の符号・各桁の数字・指数を構造化データとして取得できます。指数の絶対値が小数点以下の桁数に対応するため、より正確な桁数の取得が可能です。
from decimal import Decimal
def get_decimal_digits(value):
"""小数点以下の桁数を取得する"""
d = Decimal(str(value))
exponent = d.as_tuple().exponent
return max(0, -exponent)
# 桁数の取得例
print(get_decimal_digits(3.14)) # 2
print(get_decimal_digits(3.14159)) # 5
print(get_decimal_digits(100.0)) # 1
print(get_decimal_digits(42)) # 0
# as_tupleの詳細を確認
d = Decimal("3.14159")
print(d.as_tuple())
# DecimalTuple(sign=0, digits=(3, 1, 4, 1, 5, 9), exponent=-5)
上記のコードでは、Decimal(str(value))で文字列経由のDecimalオブジェクトを生成し、as_tuple().exponentで指数を取得しています。指数が-5であれば小数点以下5桁を意味するため、符号を反転させた値が桁数になります。
この方法でもfloatからの変換時にstr()を経由するため、floatの内部表現に依存する点は同じです。最初から正確な桁数の管理が必要な場合は、値の入力段階からDecimalオブジェクトとして扱うことを推奨します。
Pythonのfloat型の桁数に関するよくある質問
round()で四捨五入すると結果がずれるのはなぜですか?
原因は2つあります。1つ目は、Pythonのround()関数が「偶数丸め(銀行家の丸め)」を採用しているため、値がちょうど中間の場合は最も近い偶数に丸められることです。
2つ目は、floatが2進数で数値を表現しているため、10進数では中間値に見えても内部的には僅かにずれていることです。たとえば、round(2.675, 2)が2.68ではなく2.67になるのはこの2進数表現の誤差が原因です。
| 式 | 結果 | 理由 |
|---|---|---|
| round(0.5) | 0 | 最も近い偶数は0 |
| round(1.5) | 2 | 最も近い偶数は2 |
| round(2.5) | 2 | 最も近い偶数は2 |
| round(3.5) | 4 | 最も近い偶数は4 |
一般的な四捨五入(0.5を常に切り上げ)を行いたい場合は、DecimalモジュールのROUND_HALF_UPを使用してください。
f-stringとformat()はどちらを使うべきですか?
Python 3.6以降の環境であれば、f-stringの使用を推奨します。f-stringはformat()メソッドと比較してコードが短く読みやすい上に、実行速度も高速です。
| 比較項目 | f-string | format() |
|---|---|---|
| 対応バージョン | Python 3.6以降 | Python 3.0以降 |
| 可読性 | 高い | やや低い |
| 実行速度 | 高速 | f-stringより遅い |
| 動的フォーマット | 対応可能 | 対応可能 |
format()メソッドが適しているのは、フォーマット文字列をテンプレートとして外部から受け取る場合や、Python 3.5以前の環境で動作させる必要がある場合に限られます。
floatの有効桁数は何桁ですか?
Pythonのfloat型はIEEE 754倍精度浮動小数点数で、有効桁数は10進数で約15〜17桁です。これはfloat型の仮数部が53ビットで構成されていることに起因しています。
sys.float_info.digの値は15で、これは「15桁以下の10進数をfloatに変換し、再び10進に戻しても元の値が復元される」ことを意味します。16桁以降は往復変換で値がずれる可能性があります。
| 属性 | 値 |
|---|---|
| 仮数部のビット数 | 53ビット |
| 有効桁数(10進数) | 約15〜17桁 |
| 最大値 | 約1.8 × 10^308 |
| 最小正数(非正規化数) | 約5.0 × 10^-324 |
15桁を超える精度が必要な場合は、Decimalモジュールを使用してください。Decimalモジュールではgetcontext().precで任意の有効桁数を設定できます。
※上記コンテンツの内容やソースコードはAIで確認・デバッグしておりますが、間違いやエラー、脆弱性などがある場合は、コメントよりご報告いただけますと幸いです。
ITやプログラミングに関するコラム
PCを再起動するコマンド一覧
CapsLock以外で大文字になる原因【Windows編】
パソコンで大文字になるのを解除する方法
面白いAIの活用事例を業界別に紹介
Gitでcommit(コミット)を取り消す方法
Gitでブランチ(branch)を作成する方法
crontabの書き方
PDFをExcelに変換する方法
Excelでプルダウンを設定する方法
エクセルでページ区切りを設定する方法
ITやプログラミングに関するニュース
ちとせ交友会が理念伴走型AI「AIちこちゃん」を導入、2,000名超の保育職員を支援
フィルインが群馬県の中小企業向けDX支援「漸進型DX」を開始、社内人材育成を軸にした段階的推進モデルを提供
LinkholaがAI空調省エネのクレジット方法論を策定、EARTHSTORYで国内初の運用開始
VarealがAI自動受電応答システムを開発、CRM連携で電話対応業務の効率化を実現
HikvisionがAI検索「AcuSeek」を大幅更新、日本語対応の新ファームウェアと耐環境モデルが登場
クラウドエースがAI活用企業のデータ品質調査を公開、85.6%がデータ不備で難航を経験
AI翻訳「BLUE ONE」が画像翻訳機能を正式リリース、デザイン維持のまま画像内テキストを自動変換
SMBCリーガルXが契約管理「LegalXross」に生成AI検索「AIと探す(ベータ版)」を提供開始
PeopleXがAI面接の途中退席後に再開できる特許技術を取得、応募者と採用担当者の双方を支援
KDDIアイレットがキャリア採用に「AI面接」を本格導入、選考期間の約5日短縮を実現
