[英]Round python decimal to nearest 0.05
我試圖將十進制中的貨幣數字四舍五入到最接近的 0.05。 現在,我正在這樣做:
def round_down(amount):
amount *= 100
amount = (amount - amount % 5) / Decimal(100)
return Decimal(amount)
def round_up(amount):
amount = int(math.ceil(float(100 * amount) / 5)) * 5 / Decimal(100)
return Decimal(amount)
有沒有什么辦法可以更優雅地做到這一點,而無需使用 python Decimals(可能使用 quantize)處理浮點數?
對於浮動,只需使用round(x * 2, 1) / 2
。 但是,這並不能控制舍入方向。
使用Decimal.quantize
您還可以完全控制舍入的類型和方向(Python 3.5.1):
>>> from decimal import Decimal, ROUND_UP
>>> x = Decimal("3.426")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.45')
>>> x = Decimal("3.456")
>>> (x * 2).quantize(Decimal('.1'), rounding=ROUND_UP) / 2
Decimal('3.5')
首先要注意(四舍五入意外),只是有時會出現此問題時,數字緊接下面(左側),你要四舍五入到數字有5
。
即
>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01
但是有一個簡單的解決方案,我發現它似乎總是有效,並且不依賴於其他庫的import
。 解決方案是添加一個1e-X
,其中X
是您嘗試在 plus 1
上使用round
的數字字符串的長度。
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*6),2)
0.08
啊哈! 所以基於此我們可以制作一個方便的包裝函數,它是獨立的,不需要額外的import
調用......
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1))
基本上,這會增加一個值,該值保證小於您嘗試使用round
入的字符串的最小給定數字。 通過添加這個小數量,它在大多數情況下保留了round
的行為,同時確保如果低於被四舍五入的數字是5
則向上舍入,如果是4
則向下舍入。
使用10**(-len(val)-1)
是經過深思熟慮的,因為它是您可以添加的最大小數以強制轉換,同時還確保您添加的值永遠不會改變舍入,即使是小數.
不見了。 我可以只使用10**(-len(val))
和條件if (val>1)
再減去1
......但總是減去1
更簡單,因為這不會改變適用范圍此解決方法可以正確處理十進制數。 如果您的值達到類型的限制,則此方法將失敗,這將失敗,但對於幾乎整個有效十進制值范圍,它都應該有效。
您也可以使用十進制庫來完成此操作,但我建議的包裝器更簡單,並且在某些情況下可能是首選。
適用於任何舍入基數的更通用的解決方案。
from decimal import ROUND_DOWN
def round_decimal(decimal_number, base=1, rounding=ROUND_DOWN):
"""
Round decimal number to the nearest base
:param decimal_number: decimal number to round to the nearest base
:type decimal_number: Decimal
:param base: rounding base, e.g. 5, Decimal('0.05')
:type base: int or Decimal
:param rounding: Decimal rounding type
:rtype: Decimal
"""
return base * (decimal_number / base).quantize(1, rounding=rounding)
例子:
>>> from decimal import Decimal, ROUND_UP
>>> round_decimal(Decimal('123.34'), base=5)
Decimal('120')
>>> round_decimal(Decimal('123.34'), base=6, rounding=ROUND_UP)
Decimal('126')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.05'))
Decimal('123.30')
>>> round_decimal(Decimal('123.34'), base=Decimal('0.5'), rounding=ROUND_UP)
Decimal('123.5')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.