Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将python十进制四舍五入至最接近的0.05_Python_Rounding - Fatal编程技术网

将python十进制四舍五入至最接近的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)

我想把十进制的货币数字四舍五入到最接近的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小数(可能使用quantize)处理浮点数而更优雅地实现这一点?

对于浮点数,只需使用
舍入(x*2,1)/2
。不过,这并不能控制取整方向

使用
Decimal.quantize
还可以完全控制舍入的类型和方向(Python 3.5.1):

首先请注意,此问题(意外的向下舍入)仅在您要舍入到的数字的下一位(左边)有一个
5时才会发生

i、 e

但是有一个简单的解决方案,我发现它似乎总是有效的,它不依赖于额外库的导入。解决方案是添加一个
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))
基本上,这会添加一个值,该值保证小于您尝试使用的字符串的最小给定位数。通过添加少量,它在大多数情况下保留了
舍入
的行为,同时现在确保低于被舍入的数字是否为
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')