简体   繁体   English

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

[英]Pythonic way to round a float to specific min AND max number of decimal places

I would like to implement a function round(num, min, max) that rounds a float to at least min decimal places and at most max . 我想实现一个函数round(num, min, max) ,该函数将浮点数至少round(num, min, max)min小数位和max I want it to return a string. 我希望它返回一个字符串。 I have something that works, but it was surprisingly long. 我有一些有效的方法,但是时间太长了。 Can you write something more pythonic than me? 你能写比我更pythonic的东西吗?

Usage 用法

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'

I think you get the idea. 我想你应该已经明白了。 Here's what I've got. 这就是我所拥有的。

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

You're confusing float rounding with print formatting. 您将浮点数舍入与打印格式混淆。 * *

The float 3.14 is a different number than 3.1415 . 浮点数3.143.1415不同。 So rounding 3.1415 to 2 digits makes sense. 因此,将3.1415舍入到2位数字是有意义的。

But the float 3.00 is the exact same number as 3.0 . 但是float 3.003.0完全相同。 So rounding 3.0 to 2 digits isn't going to do anything; 因此,将3.0舍入到2位数将无济于事。 it's still going to be the same thing you started with. 它仍然与开始时一样。

Meanwhile, if you want to change the way numbers are printed out, you can do that using the format function, the str.format method, f-strings, % formatting, etc. For example: 同时,如果要更改数字的打印方式,可以使用format函数, str.format方法,f字符串, %格式设置等来完成。例如:

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

See Format Specification Mini-Language for details on how to use f-strings (and str.format and format ), and printf -Style String Formatting for details on how to use % . 格式化规范的迷你语言有关如何使用F-字符串(和细节str.formatformat ),以及printf风格的字符串格式化有关如何使用细节%


* Either that, or you're expecting floats to keep track of their precision and preserve it through a chain of operations. *或者,或者您期望float跟踪其精度并通过一系列操作来保持精度。 If that's what you're after, floats can't do that, but decimal.Decimal can, so you may want to look at the decimal module. 如果那是您想要的,则浮点数不能做到这一点,而decimal.Decimal可以。 decimal可以,因此您可能需要查看decimal模块。 But I don't think that's what you want here. 但我认为这不是您想要的。

Just some small improvements, but keeping the basic idea (convert value, strip zeroes, strip trailing decimal point). 只是一些小的改进,但保持基本思路(转换价值,带零,带尾随小数点)。

First change is to avoid name clash with builtin functions min and max . 第一个更改是避免使用内置函数minmax发生名称冲突。 I think that using functions designed for the particular purpose ( str.format for value formatting, str.rstrip for stripping from right, str.endswith for testing the last character) makes it little bit more pythonic. 我认为,使用专为特定目的的功能( str.format的价值格式化, str.rstrip从右侧剥离, str.endswith用于测试的最后一个字符),使得它有点更Python。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM