後続ゼロなしの浮動小数点のフォーマット


181

後続のゼロが含まれないように浮動小数点をフォーマットするにはどうすればよいですか?つまり、結果の文字列をできるだけ短くしたいのです。

例えば:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"

その例はまったく意味がありません。 3.14 == 3.140- 同じ浮動小数点数です。その点では、3.140000は同じ浮動小数点数です。そもそもゼロは存在しません。
S.Lott、2014年

33
@ S.Lott-問題は、2つの数値の実際の等価ではなく、末尾のゼロなしで浮動小数点数を印刷することだと思います。
ポクスタッド

1
@pokstad:その場合、「余分な」ゼロはありません。 %0.2fそして%0.3f左側の最後の数字を生成するために必要な2つの形式です。%0.2f右側の最後の2つの数値を生成するために使用します。
S.Lott、2014年

6
3.0 -> "3"まだ有効なユースケースです。期待どおりのprint( '{:,g}'.format( X )出力3がどこX = 6 / 2でいつX = 5 / 2得られたかを出力するの2.5に役立ちました。
ShoeMaker 2016

1
古い質問ですprint("%s"%3.140)が、あなたが望むものをあなたに与えます。(私は下に回答を追加しました...)
drevicko

回答:


178

私、そうします('%f' % x).rstrip('0').rstrip('.')-科学的記法などではなく、固定小数点形式を保証します。そうです、そうではなく、洗練されたエレガント%gではありません%g。 -)。


6
それに関する唯一の問題は、'%.2f' % -0.0001あなたに、-0.00そして最終的にあなたを残すことです-0
コス

3
@ alexanderlukanin13デフォルトの精度は6であるため、docs.python.org / 2 / library / string.htmlを参照してください'f' Fixed point. Displays the number as a fixed-point number. The default precision is 6.。上記のソリューションでは '%0.7f'を使用する必要があります。
derenio 2015

3
@derenio良い点:-) 奇妙なことが発生し始める'%0.15f'ので、上記の精度を上げることは悪い考えだと私は付け加えることができます。
alexanderlukanin13

1
他の文字列の真ん中にいる場合: print('In the middle {} and something else'.format('{:f}'.format(a).rstrip('0')))
フォールトトレラントな

1
@Alex Martelli、double rstripコマンドを取り除きます。使用すると、単に代わりに、このドットの両方を除去するために(.)とすべて一回の操作で、その後のゼロを末尾:('%f' % x).rstrip('.0')
ガブリエルステープルズ

143

%gこれを達成するために使用できます:

'%g'%(3.140)

または、Python 2.6以降の場合:

'{0:g}'.format(3.140)

ドキュメントからformatg原因(とりわけ)

意味のない後続のゼロは[仮数]から削除され、その後に残りの数字がない場合は小数点も削除されます。


28
おお、ほぼ!浮動小数点数を科学表記( "2.342E + 09")でフォーマットする場合があります。オフにすることはできますか?つまり、常にすべての有効数字を表示しますか?
TarGz 2010年

5
使用'{0:...}'.format(value)できるのになぜ使用するのformat(value, '...')ですか?これにより、空のテンプレート文字列からフォーマット指定子を解析する必要がなくなります。
Martijn Pieters

2
@MartijnPieters:形式指定子を解析するための非常に小さなコストは、他のオーバーヘッドAFAICTによって圧倒されます。実際には、3.6でのローカルベンチマーク(実際のコードを正確にモデル化するためのマイクロベンチマークのスコープ)は、format(v, '2.5f')よりも10%長くかかり'{:2.5f}'.format(v)ます。str調整しなかったとしても、メソッドフォームを使用する傾向があります。調整したり、値を追加したりする必要がある場合、変更する必要が少ないからです。もちろん、3.6の時点では、ほとんどの目的でf-stringが使用されています。:-)
ShadowRanger 2018

5
Python 3.6では、これはfloat変数のf"{var:g}"場所に短縮できvarます。
TheGreatCabbage

12

最も簡単でおそらく最も効果的なアプローチを試してみませんか?メソッドnormalize()は、すべての右端の後続ゼロを削除します。

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

作品のPython 2Pythonの3

- 更新しました -

@ BobStein-VisiBoneが指摘した唯一の問題は、10、100、1000などの数値が指数表現で表示されることです。これは、代わりに次の関数を使用して簡単に修正できます。

from decimal import Decimal


def format_float(f):
    d = Decimal(str(f));
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

2
除いてはDecimal('10.0').normalize()なり'1E+1'
ボブ・スタイン

11

いくつかの同様の質問に対する回答を検討した後、これは私にとって最良の解決策のようです:

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')

私の推論:

%g 科学的表記を取り除きません。

>>> '%g' % 0.000035
'3.5e-05'

小数点以下15桁は奇妙な動作を回避しているようで、私のニーズには十分な精度があります。

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

format(inputValue, '.15f').代わりに使用することもできまし'%.15f' % inputValueたが、少し遅くなります(約30%)。

を使用することもできましたがDecimal(inputValue).normalize()、これにはいくつかの問題もあります。一つには、それは非常に遅い(〜11倍)です。また、精度は非常に高いものの、を使用すると精度が低下することがわかりましたnormalize()

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

最も重要なことに、私はまだあなたがそこに入れた数以外の何かであなたを終わらせることができるからからに変換しDecimalfloatいます。Decimal演算がDecimalそのままDecimalで、文字列で初期化されている場合に最適に機能すると思います。

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

の精度の問題はDecimal.normalize()コンテキスト設定を使用して必要なものに調整できると確信していますが、すでに遅い速度でばかげた精度を必要とせず、フロートから変換して精度を失うことを考えると、追求する価値があったとは思わない。

-0.0は有効な浮動小数点数であり、いずれにしてもまれに発生する可能性があるため、考えられる「-0」の結果については気にしていませんが、文字列の結果をできるだけ短くしたいと述べたので、非常に少ない追加速度コストで追加条件を常に使用できます。

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result

1
残念ながら、小数点以下の左側に5桁以上ある数字でのみ機能します。たとえばfloatToString(12345.6)戻ります'12345.600000000000364'%.15fこの例では、15を減らすと数値が小さくなりますが、数値が大きくなるにつれて、その値を徐々に小さくする必要があります。数値のlog-base-10に基づいて動的に計算できますが、それはすぐに非常に複雑になります。
JohnSpeeks 2017年

1
その問題を解決する1つの方法は、(むしろ、小数点以下の桁だけよりも)全体の数の長さを制限するかもしれません:result = ('%15f' % val).rstrip('0').rstrip('.').lstrip(' ')
ティモシー・スミス

@JohnSpeeksこれが回避可能かどうかわかりません。これは、左側でより多くの桁が必要な場合に、浮動小数点数が精度を表すことができないという副作用です。私が知ることができることから、文字列として出力される数は、floatとして入力される数と同じか、少なくともその最も近い表現です。>>>12345.600000000000364 == 12345.6 True
PolyMesh

私は別の解決策を書きました。
新妻

8

ここに私のために働いた解決策があります。それはのブレンドだソリューションによって、あるpolyMesh新しいのと使用.format() 構文

for num in 3, 3., 3.0, 3.1, 3.14, 3.140:
    print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))

出力

3
3
3
3.1
3.14
3.14

この問題の唯一の誤りは、10進数の適切な数を設定する必要があることです。高い値を設定するほど、より正確な数値を表すことができますが、これを頻繁に行うと、パフォーマンスが低下する可能性があります。
beruic

1
beruicのコメントに加えて3.141.2fハードコーディングされているため、これは精度の高い浮動小数点(たとえば)では機能しません。
TrebledJ

3

これを実現するには、単にformat()を使用します。

format(3.140, '.10g') ここで、10は希望する精度です。


2
>>> str(a if a % 1 else int(a))

どういう意味int(a) if a % 1 else aですか?
beruic

Beruic様、あなたの答えは否定的な答えになります。a if a % 1 else int(a)正しい。質問には文字列の出力が必要なので、追加しましたstr
Shameem

ああ、もうわかった。a % 1ゼロでないので真実です。私はそれを暗黙的かつ誤ってとして認識しましたa % 1 == 0
beruic

2

書式設定はほとんどのPython的な方法である可能性が高いですが、more_itertools.rstripツールを使用した代替ソリューションを次に示します。

import more_itertools as mit


def fmt(num, pred=None):
    iterable = str(num)
    predicate = pred if pred is not None else lambda x: x in {".", "0"}
    return "".join(mit.rstrip(iterable, predicate))

assert fmt(3) == "3"
assert fmt(3.) == "3"
assert fmt(3.0) == "3"
assert fmt(3.1) == "3.1"
assert fmt(3.14) == "3.14"
assert fmt(3.140) == "3.14"
assert fmt(3.14000) == "3.14"
assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"

数値は、述語を満たす末尾の文字が取り除かれた文字列に変換されます。関数定義fmtは必須ではありませんが、ここでは、すべて合格したアサーションをテストするために使用されます。注:文字列入力で機能し、オプションの述語を受け入れます。

このサードパーティライブラリの詳細もご覧くださいmore_itertools


1

3.と3.0が "3.0"と表示されていても問題ない場合は、浮動小数点表現からゼロを右にストリップする非常に単純な方法です。

print("%s"%3.140)

(例外を指摘してくれた@ellimilialに感謝)


1
しかしprint("%s"%3.0)そうです。
エリミリアル

1

QuantiPhyパッケージの使用はオプションです。通常、単位とSIスケールファクターを使用して数値を処理する場合、QuantiPhyが使用されますが、数値の書式設定にはさまざまなオプションがあります。

    >>> from quantiphy import Quantity

    >>> cases = '3 3. 3.0 3.1 3.14 3.140 3.14000'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:p}')
          3 -> 3
         3. -> 3
        3.0 -> 3
        3.1 -> 3.1
       3.14 -> 3.14
      3.140 -> 3.14
    3.14000 -> 3.14

そして、この状況ではe-notationを使用しません:

    >>> cases = '3.14e-9 3.14 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case)
    ...    print(f'{case:>7} -> {q:,p}')
    3.14e-9 -> 0
       3.14 -> 3.14
     3.14e9 -> 3,140,000,000

あなたが好むかもしれない別の方法は、おそらく単位で、SIスケール係数を使用することです。

    >>> cases = '3e-9 3.14e-9 3 3.14 3e9 3.14e9'.split()
    >>> for case in cases:
    ...    q = Quantity(case, 'm')
    ...    print(f'{case:>7} -> {q}')
       3e-9 -> 3 nm
    3.14e-9 -> 3.14 nm
          3 -> 3 m
       3.14 -> 3.14 m
        3e9 -> 3 Gm
     3.14e9 -> 3.14 Gm

0

OPは余分なゼロを削除し、結果の文字列をできるだけ短くしたいと考えています。

%g指数形式は、非常に大きい値と非常に小さい値の結果の文字列を短くします。この問題は、128.0などの非常に大きいものでも非常に小さいものでもない指数表記を必要としない値で発生します。

Decimal.normalizeが長すぎる文字列を作成する場合にのみ%g指数表記を使用する短い文字列として数値をフォーマットする1つの方法を次に示します。これは最速のソリューションではない可能性があります(Decimal.normalizeを使用しているため)

def floatToString (inputValue, precision = 3):
    rc = str(Decimal(inputValue).normalize())
    if 'E' in rc or len(rc) > 5:
        rc = '{0:.{1}g}'.format(inputValue, precision)        
    return rc

inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0]

outputs = [floatToString(i) for i in inputs]

print(outputs)

# ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']



0

ここに答えがあります:

import numpy

num1 = 3.1400
num2 = 3.000
numpy.format_float_positional(num1, 3, trim='-')
numpy.format_float_positional(num2, 3, trim='-')

「3.14」と「3」を出力

trim='-' 末尾のゼロと10進数の両方を削除します。


-1

十分な幅のある%gを使用します(例: '%.99g')。かなり大きな数の場合は、固定小数点表記で印刷されます。

編集:それは動作しません

>>> '%.99g' % 0.0000001
'9.99999999999999954748111825886258685613938723690807819366455078125e-08'

1
.99幅ではなく精度です。ちょっと便利ですが、実際の精度をこのように設定することはできません(自分で切り捨てる以外は)。
Kos

-1

次のmax()ように使用できます:

print(max(int(x), x))


1
xが負の場合を考慮する必要があります。 if x < 0: print(min(x), x) else : print(max(x), x)
ThunderPhoenix 2018

json stringifyを実行するときに便利な方法です。float 1.0はint 1に変更されるため、javascriptと同じように実行されます。
ping

-3

あなたはそのようなほとんどのpython的な方法でそれを達成することができます:

python3:

"{:0.0f}".format(num)

あなたが正しい。最も簡単な方法は、「{:g}」。format(num)を使用することです
Pyglouthon

-4

%fを処理するので、

%.2f

、ここで:.2f == .00浮動小数点数。

例:

「価格:%.2f」%の価格を印刷[製品]

出力:

価格:1.50


1
これは質問が望んでいることではなく明確に述べられています。反対票を投じる必要があります。
エピソード
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.