末尾のゼロが含まれないようにフロートをフォーマットするにはどうすればよいですか?つまり、結果の文字列をできるだけ短くしたいのです。
例えば:
3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
末尾のゼロが含まれないようにフロートをフォーマットするにはどうすればよいですか?つまり、結果の文字列をできるだけ短くしたいのです。
例えば:
3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
私はそうします('%f' % x).rstrip('0').rstrip('.')
-科学的記数法などではなく、固定小数点形式を保証します。ええ、それほど洗練されていなくてエレガントではありませんが、それは機能します(そして、科学的記数法を絶対に使用しない%g
ように強制する方法がわかりません。 %g
-)。
これを達成するために使用できます%g
:
'%g'%(3.140)
または、Python≥2.6の場合:
'{0:g}'.format(3.140)
または、Python≥3.6の場合:
f'{3.140:g}'
のドキュメントからformat
:g
原因(とりわけ)
仮数から重要でない末尾のゼロ[予定]が削除され、それに続く桁が残っていない場合は小数点も削除されます。
いくつかの同様の質問に対する回答を調べた後、これは私にとって最良の解決策のようです。
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()
ましたが、これにもいくつかの問題があります。一つには、それはかなり遅い(〜11x)。また、精度はかなり高いものの、を使用すると精度が低下することもわかりましたnormalize()
。
>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
最も重要なことは、私はまだあなたがそこに入れた数以外のものになってしまう可能性Decimal
のあるからに変換しているでしょう。算術演算がそのままで、が文字列で初期化されている場合に最適に機能するfloat
と思います。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
最も簡単でおそらく最も効果的なアプローチを試すのはどうですか?normalize()メソッドは、右端の末尾のゼロをすべて削除します。
from decimal import Decimal
print (Decimal('0.001000').normalize())
# Result: 0.001
Python2およびPython3で動作します。
- 更新しました -
@ 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()
format()を使用するだけで、次のことが可能になります。
format(3.140, '.10g')
ここで、10は必要な精度です。
フォーマットはほとんどの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
。
>>> str(a if a % 1 else int(a))
数値入力または文字列入力の両方で機能するものが必要な場合:
def num(s):
""" 3.0 -> 3, 3.001000 -> 3.001 otherwise return s """
s = str(s)
try:
int(float(s))
return s.rstrip('0').rstrip('.')
except ValueError:
return s
>>> for n in [3, 3., 3.0, 3.1, 3.14, 3.140, 3.001000 ]: print(num(n))
...
3
3
3
3.1
3.14
3.14
3.001
>>> for n in [3, 3., 3.0, 3.1, 3.14, 3.140, 3.001000 ]: print(num(str(n)))
...
3
3
3
3.1
3.14
3.14
3.001
QuantiPhyパッケージの使用はオプションです。通常、QuantiPhyは、単位とSIスケール係数を使用して数値を処理するときに使用されますが、さまざまな優れた数値フォーマットオプションがあります。
>>> 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
また、この状況では電子表記を使用しません。
>>> 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
答えは次のとおりです。
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='-'
末尾のゼロと小数の両方を削除します。
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']
フロートの場合、これを使用できます。
def format_float(num):
return ('%i' if num == int(num) else '%s') % num
試して:
>>> format_float(1.00000)
'1'
>>> format_float(1.1234567890000000000)
'1.123456789'
Decimalについては、こちらのソリューションをご覧ください:https ://stackoverflow.com/a/42668598/5917543
3.と3.0が「3.0」として表示されている状態で生活できる場合は、フロート表現からゼロを右に削除する非常に単純なアプローチです。
print("%s"%3.140)
(例外を指摘してくれた@ellimilialに感謝します)
これを試してみると、「精度」変数を追加して、必要な小数点以下の桁数を設定できます。切り上げられることを覚えておいてください。これは、文字列に小数が含まれている場合にのみ機能することに注意してください。
number = 4.364004650000000
precision = 2
result = "{:.{}f}".format(float(format(number).rstrip('0').rstrip('.')), precision)
出力
4.364004650000000
4.36
十分な幅の%gを使用します(例:'%.99g')。適度に大きな数の場合は、固定小数点表記で出力されます。
編集:それは動作しません
>>> '%.99g' % 0.0000001
'9.99999999999999954748111825886258685613938723690807819366455078125e-08'
max()
次のように使用できます。
print(max(int(x), x))
"{:.5g}".format(x)
これを使用して、フロートをトレイルゼロにフォーマットします。
あなたはそのようなほとんどのpythonicな方法でそれを達成することができます:
python3:
"{:0.0f}".format(num)
%fを処理すると、
%.2f
、ここで:.2f==.00フロート。
例:
印刷"価格:%。2f"%価格[製品]
価格:1.50