Pythonic方法将浮点数舍入到特定的最小和最大小数位数

时间:2018-03-17 05:42:00

标签: python floating-point rounding

我想实现一个函数round(num, min, max),它将浮点数舍入到至少min个小数位且最多max。我希望它返回一个字符串。我有一些有用的东西,但它出人意料地长了。你能写一些比我更蟒蛇的东西吗?

用法

round(3.14159, 2, 4) --> '3.1416'
round(3.14159, 0, 2) --> '3.14'
round(3.14159, 0, 1) --> '3.1'
round(3.14159, 0, 0) --> '3'
round(3.14159, 4, 6) --> '3.141590'
round(3.14, 4, 6)    --> '3.1400'
round(3, 4, 6)       --> '3.0000'

我想你明白了。这就是我所拥有的。

def normalize(amount, min=0, max=2):
    """
    Rounds to a variable number of decimal places - as few as necessary in the range [min,max]
    :param amount: A float, int, decimal.Decimal, or string.
    :param min: the minimum number of decimal places to keep
    :param max: the maximum number of decimal places to keep
    :return: string.
    """
    if not amount:
        return amount

    # To Decimal, round to highest desired precision
    d = round(Decimal(amount), max)
    s = str(d)

    # Truncate as many extra zeros as we are allowed to
    for i in range(max-min):
        if s[-1] == '0':
            s = s[:-1]

    # Lose a trailing decimal point.
    if s[-1] == '.':
        s = s[:-1]

    return s

2 个答案:

答案 0 :(得分:1)

您将浮动舍入与打印格式混淆。 *

浮动3.143.1415的数字不同。因此将3.1415四舍五入为2位是有意义的。

但浮动3.003.0完全相同。因此将3.0四舍五入为2位数不会做任何事情;它仍然与你开始时一样。

同时,如果您想更改数字的打印方式,可以使用format函数,str.format方法,f字符串,%格式等进行更改例如:

>>> pi = 3.1415
>>> indianapi = round(pi, 0)
>>> indianapi
3.0
>>> f'{indianapi:.3f}'
'3.000'

有关如何使用f字符串(以及str.formatformat)和Format Specification Mini-Language的详细信息,请参阅printf-Style String Formatting,了解有关如何使用%的详细信息

*或者,或者你期望花车跟踪它们的精确度并通过一系列操作来保存它们。如果这就是你所追求的,浮点数不能那么做,但是decimal.Decimal可以,所以你可能想要查看decimal模块。但我不认为这就是你想要的。

答案 1 :(得分:1)

只是一些小的改进,但保持基本的想法(转换值,条带零,带尾随小数点)。

第一个更改是避免与内置函数minmax发生名称冲突。我认为使用为特定目的而设计的函数(str.format用于值格式化,str.rstrip用于从右边剥离,str.endswith用于测试最后一个字符)使得它更加pythonic。

def round(amount, dmin, dmax):
    assert 0 <= dmin <= dmax
    astr = '{:.{prec}f}'.format(amount, prec=dmax)
    if dmax != dmin:
        astr = astr[:dmin-dmax] + astr[dmin-dmax:].rstrip('0')
        if astr.endswith('.'):
            astr = astr[:-1]
    return astr