a
を 13.95 に四捨五入したい。
>>> 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("{0:.2f}".format(a))
13.95
>>> print("{0:.2f}".format(round(a,2)))
13.95
>>> print("{0:.15f}".format(round(a,2)))
13.949999999999999
通貨のように小数点以下2桁しかない場合は、2、3の選択肢があります。1)整数を使用し、ドルではなくセントで値を格納してから、100で割ってドルに変換します。 2)または decimal のような固定小数点数を使用します。
新しいフォーマット仕様があります、 文字列フォーマット仕様ミニ言語 :
あなたは同じことをすることができます:
"{0:.2f}".format(13.949999999999999)
注 上記は文字列を返すことに注意してください。フロートとして取得するには、単にfloat(...)
でラップします。
float("{0:.2f}".format(13.949999999999999))
注 float()
でラップしても何も変わらない:
>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{0:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
最も簡単な方法はformat()
関数を使うことだと私は思います。
例えば:
a = 13.949999999999999
format(a, '.2f')
13.95
これは、小数点以下2桁に丸められたストリングとして浮動小数点数を生成します。
ほとんどの数値は、floatで正確に表すことはできません。それがあなたの数式やアルゴリズムが必要とするものであるためにあなたが数を四捨五入したいなら、あなたは四捨五入を使いたいです。表示を一定の精度に制限したいだけの場合は、roundを使用せずに、単にその文字列としてフォーマットします。 (いくつかの代替丸め方法で表示したいが、トンがある場合は、2つの方法を組み合わせる必要があります。)
>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'
そして最後に、おそらく最も重要なことですが、もしあなたが exact /数学を望むのであれば、あなたはフロートを望んでいません。通常の例は、お金を扱い、「セント」を整数として格納することです。
つかいます
print"{:.2f}".format(a)
の代わりに
print"{0:.2f}".format(a)
後者は、複数の変数を出力しようとすると出力エラーになる可能性があるためです(コメントを参照)。
以下のコードを試してください。
>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
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は preferred です。
オプション2の詳細については、 Pythonのドキュメントの文字列フォーマット に関するリンクをお勧めします。
そしてオプション1の詳細については、 このリンクで十分で、さまざまなフラグに関する情報があります 。
出力フォーマットは変更できます。
>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
入出力の丸め問題は、Python 2.7.0によって最終的に解決されましたおよび3.1です。
正しく丸められた数は可逆的に前後に変換することができます。str -> float() -> repr() -> float() ...
またはDecimal -> float -> str -> Decimal
Decimal型は格納には不要です。
(もちろん、累積された最後のビットエラーを取り除くために丸められた数の加算または減算の結果を丸める必要があるかもしれません。明示的な10進数算術はまだ便利ですがstr()
によるストリングへの変換極端な精度も極端な数の連続した算術演算も必要とされない場合、通常は十分に十分です。)
無限テスト:
import random
from decimal import Decimal
for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-)
assert float(repr(x)) == x # Reversible repr() conversion.
assert float(Decimal(repr(x))) == x
assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round.
if x >= 0.1: # Implicit rounding to 12 significant digits
assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors.
y = 1000 * x # Decimal type is excessive for shopping
assert str(y) == repr(round(y, 12 - 3)) # in a supermaket with Python 2.7+ :-)
リリースノートを参照してください。Python 2.7 - その他の言語の変更 4番目の段落:
ほとんどのプラットフォームで、浮動小数点数と文字列の間のConversionsは正しく丸められたになりました。これらの変換は、さまざまな場所で発生します。浮動小数点数と複素数に対するstr()。 floatコンストラクタとcomplexコンストラクタ。数値フォーマット
marshal
、pickle
およびjson
モジュールを使用して、浮動小数点数と複素数をシリアライズおよびデシリアライズする。 Pythonコードのfloatリテラルと虚数リテラルの解析10進数から浮動小数点数への変換。これに関連して、浮動小数点数xのrepr()は、正しい丸め(round付き)の下で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番号は存在しません。結果はNiceではなく、変換repr(float(number_as_string))
はnumpyで元に戻すことができません。一方、float.__repr__
はすべての数字が重要になるようにフォーマットされています。シーケンスにギャップはなく、変換は可逆的です。単に:あなたがおそらくnumpy.float64数を持っているならば、数値プロセッサのためにではなく、人間のためにフォーマットされるために通常のfloatに変換してください、そうでなければPython 2.7+ではこれ以上必要はありません。
Python 2.7では:
a = 13.949999999999999
output = float("%0.2f"%a)
print output
まだ誰も言及していないようなので、Python 3.6のf-string/template-stringフォーマットの例を挙げてみましょう。
>>> f'{a:.2f}'
これは、演算子を使って、親を必要としない、より長い例でもうまく動作します。
>>> print(f'Completed in {time.time() - start:.2f}s')
Pythonのチュートリアルにはという浮動小数点演算:問題点と制限という付録があります。それを読んで。何が起きているのか、そしてなぜPythonが最善を尽くしているのかを説明します。それはあなたと一致する例さえあります。ちょっと引用してみましょう:
>>> 0.1 0.10000000000000001
あなたは
round()
関数を使って期待している1桁の数字に戻すことに誘惑されるかもしれません。しかし、それは違いはありません。>>> round(0.1, 1) 0.10000000000000001
問題は、
“0.1”
に格納されている2進浮動小数点値がすでに1/10
への可能な限り最良の2進近似であったことです。
0.1
は正確には1/10
ではないので、0.1
の10個の値を合計しても正確に1.0
にならない可能性があります。>>> sum = 0.0 >>> for i in range(10): ... sum += 0.1 ... >>> sum 0.99999999999999989
あなたの問題に対する一つの代替案と解決策は decimal
モジュールを使うことです。
Pythonでは小数点以下2桁まで値を丸めるために format 演算子を使用できます。
print(format(14.4499923, '.2f')) // output is 14.45
それはあなたがそれをするようにあなたが言ったことを正確にしていて、そして正しく働いています。 浮動小数点混乱についての詳細を読んでください そして代わりに decimal オブジェクトを試してください。
@Mattが指摘したように、Python 3.6はf文字列を提供しますそしてそれらはネストされたパラメータを使うこともできます:
value = 2.34558
precision = 2
width = 4
print(f'result: {value:{width}.{precision}f}')
これはresult: 2.35
を表示します
PythonやJavaScriptなどの型動的言語で浮動小数点を固定するために、私はこのテクニックを使います
# For example:
a = 70000
b = 0.14
c = a * b
print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980
次のようにDecimalを使用することもできます。
from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
orig_float = 232569 / 16000.0
14.5355625
short_float = float("{:.2f}".format(orig_float))
14.54
from decimal import Decimal
def round_float(v, ndigits=2, rt_str=False):
d = Decimal(v)
v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
if rt_str:
return v_str
return Decimal(v_str)
結果:
Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
1,2,3のように簡単です。
高速に丸められた10進数浮動小数点演算には decimal moduleを使用します。
d = 10進数(10000000.0000009)
丸めを達成するために:
d.quantize(Decimal('0.01'))
Decimal('10000000.00')
の結果になります
def round_decimal(number, exponent='0.01'):
decimal_value = Decimal(number)
return decimal_value.quantize(Decimal(exponent))
OR
def round_decimal(number, decimal_places=2):
decimal_value = Decimal(number)
return decimal_value.quantize(Decimal(10) ** -decimal_places)
シモンズ:他人の批評:フォーマットは丸めていません。
このようなラムダ関数はどうでしょうか。
arred = lambda x,n : x*(10**n)//1/(10**n)
こうすればあなたはただできる:
arred(3.141591657,2)
そして得る
3.14
数値を決意に丸めるには、次の方法が最善の方法です。これは、任意の決議で有効です(小数点以下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
Decimalオブジェクトとround()メソッドを組み合わせて使用してください。
Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')