将python十进制四舍五入至最接近的0.05
我想把十进制的货币数字四舍五入到最接近的0.05。现在,我正在这样做:将python十进制四舍五入至最接近的0.05,python,rounding,Python,Rounding,我想把十进制的货币数字四舍五入到最接近的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)
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小数(可能使用quantize)处理浮点数而更优雅地实现这一点?对于浮点数,只需使用
舍入(x*2,1)/2
。不过,这并不能控制取整方向
使用Decimal.quantize
还可以完全控制舍入的类型和方向(Python 3.5.1):
首先请注意,此问题(意外的向下舍入)仅在您要舍入到的数字的下一位(左边)有一个5时才会发生
i、 e
但是有一个简单的解决方案,我发现它似乎总是有效的,它不依赖于额外库的导入。解决方案是添加一个1e-X
,其中X
是您试图在plus1
上使用的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))
基本上,这会添加一个值,该值保证小于您尝试使用的字符串的最小给定位数。通过添加少量,它在大多数情况下保留了舍入
的行为,同时现在确保低于被舍入的数字是否为5
,如果为4
则舍入
使用10**(-len(val)-1)
的方法是经过深思熟虑的,因为它是可以用来强制移位的最大小数,同时还可以确保即使缺少小数
,您添加的值也不会改变舍入。我可以使用10**(-len(val))
和条件if(val>1)
来减去1
更多。。。但是总是减去1
更简单,因为这不会改变此解决方案可以正确处理的十进制数的适用范围。如果您的值达到类型的限制,这种方法将失败,但对于几乎整个有效的十进制值范围,它应该可以工作
您也可以使用库来实现这一点,但我建议的包装器更简单,在某些情况下可能更受欢迎
编辑:感谢您指出5
边缘情况仅适用于某些值。这是适用于任何舍入基数的更通用解决方案
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')
为什么不在python中使用回合?@SeekAddo。我怎样才能调到最接近的0.05?我还需要控制舍入方向(即我需要向上舍入/向下舍入)。def round_num(amount):print(round(amount,2))round_num(23.045954)将为您提供23.05,让我问一下,您希望向下舍入是什么样子@gurch101@SeekAddo我很确定上面两个函数的工作方式与我预期的一样。只是想寻找一个更优雅的解决方案。如果我调用四舍五入十进制(decimal('123.36'),base=decimal('0.09'))
,我会得到十进制('123.30')
。我不应该得到十进制('123.29')
?我可能遗漏了一些东西。对于十进制基数,它的工作原理就像你首先将十进制数和基数乘以基数的最低有效位“乘数”base=0.09
decimal\u number=123.36
multiplier=100
然后base=9
decimal\u numer=12336
12336/9=1370.66666666 7
1370*9=12330
12330/100=123.30
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')