[解決!Python]小数点以下の有効桁数を指定して浮動小数点数値を文字列化するには解決!Python

format関数/文字列のformatメソッド/f文字列で書式を指定して、浮動小数点数値を任意の有効桁数で文字列に変換する方法を紹介する。

» 2024年07月09日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

f = 0.123456789012345
print(f)  # 0.123456789012345

# 固定小数点表記
# format関数を使って小数点以下の桁数を指定する
result = format(f, '.10f'# 有効桁数10桁
print(result)  # 0.1234567890

# formatメソッドを使って小数点以下の桁数を指定する
result = '{:.10f}'.format(f)
print(result) # 0.1234567890

result = '{0:.10f}'.format(f)
print(result) # 0.1234567890

result = '{f:.10f}'.format(f=f)
print(result) # 0.1234567890

# f文字列を使って小数点以下の桁数を指定する
result = f'{f:.10f}'
print(result)  # 0.1234567890

# fではなくFでもよい(このときにはnanがNANになるなどの違いがある)
nan = float('nan')
result = f'{nan:.10F}'
print(result)  # NAN

# 桁数を指定しなければデフォルトでは精度は6桁(float型の場合)
result = format(f, 'f')
print(result)  # 0.123457

# 指数表記
# format関数を使って小数点以下の桁数を指定する
result = format(f, '.10e'# 有効桁数10桁
print(result)  # 1.2345678901e-01

# formatメソッドを使って小数点以下の桁数を指定する
result = '{:.10e}'.format(f)
print(result) # 1.2345678901e-01

# f文字列を使って小数点以下の桁数を指定する
result = f'{f:.10e}'
print(result)  # 1.2345678901e-01

# eではなくEでもよい(このときにはeがEになるなどの違いがある)
result = f'{f:.10E}'
print(result)  # 1.2345678901E-01

# 桁数を指定しなければデフォルトでは精度は6桁(float型の場合)
result = '{0:e}'.format(f)
print(result)  # 1.234568e-01

# 汎用フォーマット
# format関数を使って小数点以下の桁数を指定する
result = format(f, '.10g'# 有効桁数10桁
print(result)  # 0.123456789(無駄な0は省略される)

# formatメソッドを使って小数点以下の桁数を指定する
result = '{:.10g}'.format(f)
print(result) # 0.123456789

# f文字列を使って小数点以下の桁数を指定する
result = f'{f:.10g}'
print(result)  # 0.123456789

# 桁数を指定しなければデフォルトでは精度は6桁(float型の場合)
result = f'{f:g}'
print(result)  # 0.123457

# 汎用フォーマットでは固定小数点表記と指数表記が切り替わる

# 精度(p)に3を指定して以下の値を文字列化してみると……
f = 12345.6789
p = 3
tmp = f'{f:.{p - 1}e}'  # 精度にp-1を指定して指数表記の文字列を得て指数を確認
print(tmp)  # 1.23e+04:exp == 4

result = f'{f:.{p}g}'  # m(-4) <= exp(4) < p(3)は未成立→指数表記
print(result)  # 1.23e+04:f'{f:.{p-1}e}'で文字列化した結果と同じ

print(tmp == result)  # True

# 精度(p)に6を指定して以下の値を文字列化してみると……
f = 0.00123456789
p = 6
tmp = f'{f:.{p - 1}e}'  # 精度にp-1を指定して指数表記の文字列を得て指数を確認
print(tmp)  # 1.23457e-03:exp == -3

result = f'{f:.{p}g}'  # m(-4) <= exp(-3) < p(6)は成立→固定小数点表記
print(result)  # 0.00123457

exp = -3
tmp = f'{f:.{p-1-exp}f}'

print(tmp == result)  # True


表記 書式指定
固定小数点表記 .{精度}f
.{精度}F
F(精度の指定なし)
.5f/.5F/F
指数表記 .{精度}e
.{精度}E
E(精度の指定なし)
.4e/.4E/E
汎用フォーマット .{精度}g
.{精度}G
G(精度の指定なし)
.6g/.6G/G
format関数/formatメソッド/f文字列で桁数を指定して浮動小数点数値を文字列化するための書式指定

小数点以下の有効桁数(精度)を指定して浮動小数点数値を文字列化する

 Pythonに組み込みのformat関数や文字列のformatメソッド、f文字列を使うと浮動小数点数値を文字列化できる。おおよその構文を以下に示す。

format(value, format_spec='')
'書式指定文字列{:format_spec}'.format(*args, **kwargs)
f'書式指定文字列{式:format_spec}'


 format関数では文字列化したい値を第1引数に、それをどのような書式で文字列化するかを示すformat_specを第2引数に指定する。

 文字列のformatメソッドでは、'書式指定文字列'内に波かっこ「{}」で囲んだ「置換フィールド」を含め、置換フィールド内でコロン「:」に続けて埋め込む書式を指定するformat_specを指定する(文字列化したい値はformatメソッドの引数として渡す)。

 f文字列ではformatメソッドとf''内にリテラル文字列と波かっこで囲んだ置換フィールドを置き、置換フィールドには埋め込む値とコロンに続けてformat_specを記述する。

 このときにformat_spec(の一部)としてドット「.」に続けて小数点以下の有効桁数(精度)を指定して、最後にデータの表現方法として'f'/'F'/'e'/'E'/'g'/'G'を指定すると浮動小数点数値が指定したformat_specに準じた形で文字列化される。

 以降では以下の浮動小数点数値を例に、固定小数点表記/指数表記/汎用(はんよう)フォーマットで浮動小数点数値を文字列化する方法を説明していく。

f = 0.123456789012345
print(f)  # 0.123456789012345


固定小数点表記

 固定小数点表記で文字列化するには、ドットに続けて精度を、さらにデータの表現方法として'f'または'F'をformat_specに記述する。

 以下はformat関数を使う例だ。

result = format(f, '.10f'# 有効桁数10桁
print(result)  # 0.1234567890


 第2引数(format_spec)が'.10f'となっているので小数点数以下10桁の精度で文字列化されているのが分かるはずだ。

 同じことをformatメソッドでやると次のようになる。

result = '{:.10f}'.format(f)
print(result) # 0.1234567890

result = '{0:.10f}'.format(f)
print(result) # 0.1234567890

result = '{f:.10f}'.format(f=f)
print(result) # 0.1234567890


 formatメソッドでは呼び出しに使用する文字列が書式指定文字列となり、そこに波かっこで囲んで置換フィールドを記述する。これにより、formatメソッドに渡した値が文字列化される。format_specはコロンに続けて記述する。ここではformat関数の例と同様に「.10f」となっているので固定小数点表記で小数点以下が10桁となる。

 formatメソッドでは引数をさまざまな形で渡せるので、上では代表的な渡し方と、渡された値を置換フィールドで使う方法を示している。

 そして、同じことをf文字列でやると次のようになる。

result = f'{f:.10f}'
print(result)  # 0.1234567890


 f文字列内の置換フィールドには埋め込みたい値(ここでは変数f)を記述して、コロンに続けてformat_specとして「.10f」と書くことで、変数fの値が小数点以下10桁の固定小数点表記で文字列化される。

 なお、表現方法として指定する'f'は'F'でも構わない。このときには通常は'nan'や'inf'などと小文字で表現される値が大文字で表現されるようになる。

nan = float('nan')
result = f'{nan:.10F}'
print(result)  # NAN


 精度を指定せずにformat_specに'f'や'F'を指定すると、デフォルトでは浮動小数点数値の場合、6桁が指定されたものと見なされる。

result = format(f, 'f')
print(result)  # 0.123457


指数表記

 指数表記で浮動小数点数値を文字列化するには精度と'e'(または'E')をformat_specに含める。以下にformat関数/formatメソッド/f文字列を使った例を示す。

# format関数
result = format(f, '.10e'# 有効桁数10桁
print(result)  # 1.2345678901e-01

# formatメソッド
result = '{:.10e}'.format(f)
print(result) # 1.2345678901e-01

# f文字列
result = f'{f:.10e}'
print(result)  # 1.2345678901e-01


 'e'ではなく'E'を指定すると、指数表記で使われる「e」が「E」になる。

result = f'{f:.10E}'
print(result)  # 1.2345678901E-01


 精度を指定せずに'e'または'E'だけをformat_specに指定すると、浮動小数点数値の場合にはデフォルトで有効桁数が6桁になるのは固定小数点表記のときと同じだ。

result = '{0:e}'.format(f)
print(result)  # 1.234568e-01


汎用フォーマット

 汎用フォーマットは文字列化の際に、有効桁数の指定と文字列化したい値の関係によって固定小数点表記と指数表記が自動的に切り替わる。これについては後で詳しく見るとして、これまでと同様に有効桁数を10桁として文字列化する例を以下に示す。

# format関数
result = format(f, '.10g'# 有効桁数10桁
print(result)  # 0.123456789(無駄な0は省略される)

# formatメソッド
result = '{:.10g}'.format(f)
print(result) # 0.123456789

# f文字列
result = f'{f:.10g}'
print(result)  # 0.123456789


 注意してほしいのは、10桁を指定したのに9桁で表記が終わっている点だ。汎用フォーマットでは最小桁の値が「0」のときには、それが自動的に取り除かれる。上の例では小数点以下10桁目が「0」だったのでこの処理が行われている。

 これまでと同様に、format_specに制度を指定せずに'g'または'G'を指定すると、浮動小数点数値の場合は6桁が指定されたものと見なされる。

result = f'{f:g}'
print(result)  # 0.123457


汎用フォーマットでは固定小数点表記と指数表記が切り替わる例

 Pythonのドキュメント「書式指定ミニ言語」の'type'オプション(埋め込む値をどう表現するかの指定。ここでは'f'、'e'、'g'など)の説明では次のような記述がある。

suppose that the result formatted with presentation type 'e' and precision p-1 would have exponent exp. Then, if m <= exp < p, where m is -4 for floats and -6 for Decimals, the number is formatted with presentation type 'f' and precision p-1-exp. Otherwise, the number is formatted with presentation type 'e' and precision p-1.

 意訳してみると、これは次のような意味になる。「'type'オプションに'e'を、精度にp-1を指定して文字列化した結果、その指数がexpになったものとする。このとき、m(-4) <= exp < pであれば、その数値は固定小数点表記で精度にp-1-expが指定されたものとして文字列化される。そうでなければ、その数値は指数表記で精度にp-1が指定されたものとして文字列化される。」

 そこで精度(p)に3を指定して以下の値を文字列化してみよう。

f = 12345.6789
p = 3


 まずは「精度にp-1を指定して、指数表記」で上の値を文字列化してみる。

tmp = f'{f:.{p - 1}e}'  # 精度にp-1を指定して指数表記の文字列を得て指数を確認
print(tmp)  # 1.23e+04:exp == 4


 書式化後の文字列は「1.23e+04」なので指数(exp)は「4」である。このとき、「m(-4) <= exp(4) < p(3)」という式は成立しない(exp > pとなるので)。よって、精度に3を指定して汎用フォーマットで文字列化しようとすると、指数表記で精度にp-1を指定したものとして文字列化されるということだ。

result = f'{f:.{p}g}'  # m(-4) <= exp(4) < p(3)は未成立→指数表記
print(result)  # 1.23e+04:f'{f:.{p-1}e}'で文字列化した結果と同じ

print(tmp == result)  # True


 次に、精度(p)に6を指定して以下の値を文字列化してみよう。

f = 0.00123456789
p = 6


 先ほどと同様に、まずは「精度にp-1を指定して、指数表記」で上の値を文字列化してみる。

tmp = f'{f:.{p - 1}e}'  # 精度にp-1を指定して指数表記の文字列を得て指数を確認
print(tmp)  # 1.23457e-03:exp == -3


 文字列化された結果「1.23457e-03」からexpが「-3」であることが分かった。このとき、「m(-4) <= exp(-3) < p(6)」は成立する。よって、精度に6を指定して汎用フォーマットで文字列化しようとすると、固定小数点表記で精度にp-1-exp=6-1-(-3)=8を指定したものとして文字列化されるということだ。

result = f'{f:.{p}g}'  # m(-4) <= exp(-3) < p(6)は成立→固定小数点表記
print(result)  # 0.00123457


 実際に固定小数点表記で精度に8を指定して文字列化したものと比較した結果も以下に示す。

exp = -3
tmp = f'{f:.{p-1-exp}f}'

print(tmp == result)  # True


「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

AI for エンジニアリング
「サプライチェーン攻撃」対策
1P情シスのための脆弱性管理/対策の現実解
OSSのサプライチェーン管理、取るべきアクションとは
Microsoft & Windows最前線2024
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。