48

形式指定子を使用して、先頭のゼロなしで 1 未満になる float を出力しようとしています。ちょっとしたハックを思いつきましたが、フォーマット指定子の先頭のゼロを削除する方法があると思います。ドキュメントで見つけられませんでした。

問題

>>> k = .1337
>>> print "%.4f" % k
'0.1337'

ハック

>>> print ("%.4f" % k) [1:]
'.1337'
4

13 に答える 13

34

別の方法は次のとおりです。

>>> ("%.4f" % k).lstrip('0')
'.1337'

[1:]>=1 の数値でも機能するという点で、より一般的です。

ただし、どちらの方法も負の数を正しく処理しません。この点では、次のほうが優れています。

>>> re.sub('0(?=[.])', '', ("%0.4f" % -k))
'-.1337'

特にエレガントではありませんが、今のところ、より良い方法は考えられません。

于 2012-04-24T18:31:24.393 に答える
12

かわいい正規表現のトリックが好きなのと同じくらい、単純な関数がこれを行う最良の方法だと思います。

def formatFloat(fmt, val):
  ret = fmt % val
  if ret.startswith("0."):
    return ret[1:]
  if ret.startswith("-0."):
    return "-" + ret[2:]
  return ret

>>> formatFloat("%.4f", .2)
'.2000'
>>> formatFloat("%.4f", -.2)
'-.2000'
>>> formatFloat("%.4f", -100.2)
'-100.2000'
>>> formatFloat("%.4f", 100.2)
'100.2000'

startswithこれには、正規表現ではなく単純な文字列一致であるため、理解しやすいという利点があります。

于 2014-05-13T20:15:25.020 に答える
5

MyFloat組み込みクラスの代わりに、次のクラスを使用できますfloat

def _remove_leading_zero(value, string):
    if 1 > value > -1:
        string = string.replace('0', '', 1)
    return string


class MyFloat(float):
    def __str__(self):
        string = super().__str__()
        return _remove_leading_zero(self, string)

    def __format__(self, format_string):
        string = super().__format__(format_string)
        return _remove_leading_zero(self, string)

このクラスを使用すると、書式設定str.formatにモジュラス演算子 ( ) の代わりに関数を使用する必要があります。%次にいくつかの例を示します。

>>> print(MyFloat(.4444))
.4444

>>> print(MyFloat(-.4444))
-.4444

>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text .444 some more text

>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +.444 some more text

クラスのモジュラス演算子 ( %)も同じように動作させたい場合は、クラスをサブクラス化してクラスのメソッドstrをオーバーライドする必要があります。ただし、クラスのメソッドをオーバーライドするほど簡単ではありません。その場合、フォーマットされた浮動小数点数が結果の文字列の任意の位置に存在する可能性があります。__mod__str__format__float

[注: 上記のコードはすべて Python3 で書かれています。また、Python2でオーバーライド__unicode__する必要があり、呼び出しも変更する必要がありsuperます。]

PS: の公式の文字列表現も変更したい場合は、__repr__と同様のメソッドをオーバーライドすることもできます。__str__MyFloat




編集:実際には、メソッドを使用してフォーマット文字列に新しい構文を追加できます__format__。したがって、両方の動作を維持したい場合、つまり、必要な場合は先行ゼロを表示し、不要な場合は先行ゼロを表示しません。MyFloat次のようにクラスを作成できます。

class MyFloat(float):
    def __format__(self, format_string):
        if format_string.endswith('z'):  # 'fz' is format sting for floats without leading the zero
            format_string = format_string[:-1]
            remove_leading_zero = True
        else:
            remove_leading_zero = False

        string = super(MyFloat, self).__format__(format_string)
        return _remove_leading_zero(self, string) if remove_leading_zero else string
        # `_remove_leading_zero` function is same as in the first example

そして、このクラスを次のように使用します。

>>> print('some text {:.3f} some more text',format(MyFloat(.4444)))
some text 0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(.4444)))
some text .444 some more text


>>> print('some text {:+.3f} some more text',format(MyFloat(.4444)))
some text +0.444 some more text
>>> print('some text {:+.3fz} some more text',format(MyFloat(.4444)))
some text +.444 some more text


>>> print('some text {:.3f} some more text',format(MyFloat(-.4444)))
some text -0.444 some more text
>>> print('some text {:.3fz} some more text',format(MyFloat(-.4444)))
some text -.444 some more text

「f」の代わりに「fz」を使用すると、先頭のゼロが削除されることに注意してください。

また、上記のコードは Python2 と Python3 の両方で機能します。

于 2014-05-17T21:27:50.283 に答える
4

誰もそれを行うためのより数学的な方法を提案していないことに驚いています:

n = 0.123456789
'.%d' % (n*1e4)

私にはずっと素敵に見えます。:)

しかし興味深いことに、あなたのものは最速です。

$ python -mtimeit '".%d" % (0.123456789*1e4)'
1000000 loops, best of 3: 0.809 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789)).lstrip("0")'
1000000 loops, best of 3: 0.209 usec per loop
$ python -mtimeit '("%.4f"%(0.123456789))[1:]'
10000000 loops, best of 3: 0.0723 usec per loop
于 2015-12-12T18:17:21.503 に答える
4

.lstrip()文字列フォーマットを使用して文字列に変換した後、 を使用します。

>>> k = .1827412
>>> print ("%.4f"%(k)).lstrip('0')
.1827
>>> 

.lstrip()文字列の先頭の文字を削除するために使用できます。

>>> k = 'bhello'
>>> print k.lstrip('b')
hello
>>> print k.lstrip('bhel')
o
>>> print k.lstrip('bel')
hello
>>> 

ドキュメントから

string.lstrip(s[, chars])

        先頭の文字を削除した文字列のコピーを返します

于 2014-05-15T02:19:31.613 に答える
4
import re
re.sub("^(\-?)0\.", r'\1.', "%.4f" % k)

これは短くてシンプルで、うまくいかないシナリオは見つかりません。

例:

>>> import re
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 0.1337)
'.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 1.337)
'1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0)
'.0000'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -0.1337)
'-.1337'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -1.337)
'-1.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % 10.337)
'10.3370'
>>> re.sub("^(\-?)0\.", r'\1.', "%.4f" % -10.337)
'-10.3370'

編集: -10以上および10未満の数値のみを検討している場合、次のように動作します:

("%.4f", k).replace('0.', '.')
于 2014-05-13T23:23:25.077 に答える
4

私は何よりも読みやすくシンプルにしたいと思っています。記号と数値を別々に扱いましょう。そして、少しインラインの if ステートメントは、誰にも害を及ぼすことはありません。

k = -.1337
"".join( ["-" if k < 0 else "", ("%.4f" % abs(k)).lstrip('0')] )
于 2014-05-14T18:04:36.670 に答える
1

Python の標準 lib の str.format() を使用して、float 値の文字列変換を生成できます。次に、文字列を操作して、正または負の数値の最終結果を形成できます。

n = -.1234567890
print('{0}'.format('-' if n < 0 else '') + ('{:0.4}'.format(n).split('-')[1 if n < 0 else 0].lstrip('0')))
于 2014-05-18T16:14:50.647 に答える
0

Python 3 の場合

シンプルなものが必要で、負数のサポートが必要ない場合:

f'{k:.4f}'.lstrip('0')

@nettux443 による優れた正規表現など、負の数のサポートが必要な場合の解決策は他にもあります。

于 2018-11-04T15:17:53.040 に答える