13.95a
に丸めたい。
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
関数が期待どおりにround
機能しません。
すべての数値を正確に表すことができないという浮動小数点数の古い問題に直面しています。コマンドラインは、メモリからの完全な浮動小数点形式を表示しているだけです。
浮動小数点表現を使用すると、丸められたバージョンは同じ数値になります。コンピューターは2進数であるため、浮動小数点数を整数として格納し、それを2の累乗で除算します。したがって、13.95は125650429603636838 /(2 ** 53)と同様の方法で表されます。
倍精度数の精度は53ビット(16桁)で、通常の浮動小数点数の精度は24ビット(8桁)です。Pythonの浮動小数点型は、倍精度を使用して値を格納します。
例えば、
>>> 125650429603636838/(2**53)
13.949999999999999
>>> 234042163/(2**24)
13.949999988079071
>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999
小数点以下2桁だけの場合(たとえば、通貨値を表示する場合)、次の2つの選択肢があります。
Nobody here seems to have mentioned it yet, so let me give an example in Python 3.6's f-string/template-string format, which I think is beautifully neat:
>>> f'{a:.2f}'
It works well with longer examples too, with operators and not needing parens:
>>> print(f'Completed in {time.time() - start:.2f}s')
最も簡単なアプローチは関数を使用することだと思いformat()
ます。
例えば:
a = 13.949999999999999
format(a, '.2f')
13.95
これにより、小数点以下 2 桁に丸められた文字列として浮動小数点数が生成されます。
ほとんどの数値は、float では正確に表すことができません。数値を四捨五入する必要があるために数値を四捨五入する場合は、四捨五入を使用します。表示を特定の精度に制限したいだけの場合は、ラウンドを使用せず、その文字列としてフォーマットするだけです。(別の丸め方法で表示したい場合で、数が多い場合は、2 つの方法を組み合わせる必要があります。)
>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'
最後に、おそらく最も重要なことですが、正確な計算が必要な場合は、フロートはまったく必要ありません。通常の例は、お金を扱い、「セント」を整数として格納することです。
使用する
print"{:.2f}".format(a)
それ以外の
print"{0:.2f}".format(a)
後者は、複数の変数を出力しようとすると出力エラーにつながる可能性があるためです (コメントを参照)。
入力と出力の丸めの問題はPython 3.1で完全に解決され、修正は Python 2.7.0 にも移植されています。
丸められた数値は、float と string の間で前後に可逆的に変換できます
str -> float() -> repr() -> float() ...
。Decimal -> float -> str -> Decimal
>>> 0.3
0.3
>>> float(repr(0.3)) == 0.3
True
Decimal
ストレージにタイプは不要になりました。
算術演算の結果は、丸め誤差が 1 つの数値を解析した後に可能であるよりも多くの不正確さを蓄積する可能性があるため、再度丸める必要があります。これは改良されたrepr()
アルゴリズム (Python >= 3.1, >= 2.7.0) では修正されていません:
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1, 0.2, 0.3
(0.1, 0.2, 0.3)
出力文字列関数str(float(...))
は、Python < 2.7x および < 3.1 で 12 の有効な数字に丸められ、修正されていない repr() 出力と同様に過度の無効な数字を防ぎます。非常によく似た数値を減算した後でも、それはまだ不十分であり、他の操作の後に丸めすぎました。repr() は固定されていますが、Python 2.7 と 3.1 は同じ長さの str() を使用します。Numpy の一部の古いバージョンでは、固定された Python を使用していても、過度の無効な数字がありました。現在の Numpy は固定されています。Python バージョン >= 3.2 では、str() および repr() 関数の結果は同じであり、Numpy の同様の関数の出力もあります。
import random
from decimal import Decimal
for _ in range(1000000):
x = random.random()
assert x == float(repr(x)) == float(Decimal(repr(x))) # Reversible repr()
assert str(x) == repr(x)
assert len(repr(round(x, 12))) <= 14 # no excessive decimal places.
リリース ノート Python 2.7 - その他の言語の変更の 4 番目の段落を参照してください。
浮動小数点数と文字列の間の変換が、ほとんどのプラットフォームで正しく丸められるようになりました。これらの変換はさまざまな場所で行われます。浮動小数点数と複素数の str()。float および複雑なコンストラクター。数値フォーマット;
marshal
、pickle
およびjson
モジュールを使用して、浮動小数点数と複素数をシリアライズおよびデシリアライズします。Python コードでの float および imaginary リテラルの解析。10 進数から浮動小数点数への変換。これに関連して、浮動小数点数 x のrepr()は、正しい丸め (2 分の 1 から偶数への丸めモード) でx に丸められることが保証されている最短の 10 進文字列に基づいて結果を返すようになりました。以前は、x を 17 桁の 10 進数に丸めることに基づいて文字列を生成していました。
詳細: Python 2.7 より前の のフォーマットはfloat
、現在の に似ていましたnumpy.float64
。どちらのタイプも、同じ 64 ビットのIEEE 754倍精度を 52 ビットの仮数で使用します。大きな違いは、np.float64.__repr__
ビットが失われないように過剰な 10 進数で頻繁にフォーマットされることですが、13.949999999999999 と 13.950000000000001 の間に有効な IEEE 754 番号が存在しません。repr(float(number_as_string))
結果は良くなく、numpy で変換を元に戻すことはできません。一方で:float.__repr__
すべての数字が重要になるようにフォーマットされています。シーケンスにはギャップがなく、変換は可逆的です。簡単に言えば、おそらく numpy.float64 数値を持っている場合は、数値プロセッサ用ではなく人間用にフォーマットするために、それを通常の float に変換します。それ以外の場合は、Python 2.7 以降では何も必要ありません。
出力形式を変更できます。
>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Python < 3 (2.6 または 2.7 など) では、2 つの方法があります。
# Option one
older_method_string = "%.9f" % numvar
# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)
ただし、Python バージョン 3 (3.2 や 3.3 など) では、オプション 2 が優先されることに注意してください。
オプション 2 の詳細については、Python ドキュメントの文字列フォーマットに関するこのリンクをお勧めします。
オプション 1 の詳細については、このリンクで十分であり、さまざまなフラグに関する情報が含まれています。
Python では、値を小数点以下 2 桁まで丸めるためにformat演算子を使用できます。
print(format(14.4499923, '.2f')) // output is 14.45
数値を解像度に丸めるには、次の方法が最適です。これは、任意の解像度 (小数点以下 2 桁またはその他のステップの場合は 0.01) で機能します。
>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95
>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
lambda x,n:int(x*10^n+.5)/10^n は、多くの言語で長年にわたって私のために働いてきました。
お金を扱いたいならpython decimalモジュールを使う
from decimal import Decimal, ROUND_HALF_UP
# amount can be integer, string, tuple, float, or another Decimal object
def to_money(amount) -> Decimal:
money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
return money