Python:在一般情况下,a可以舍入为b

Wil*_*uck 7 python floating-point rounding

作为我正在编写的一些单元测试代码的一部分,我编写了以下函数.其目的是确定'a'是否可以舍入为'b',无论'a'或'b'有多精确.

def couldRoundTo(a,b):
    """Can you round a to some number of digits, such that it equals b?"""
    roundEnd = len(str(b))
    if a == b:
        return True
    for x in range(0,roundEnd):
        if round(a,x) == b:
            return True
    return False
Run Code Online (Sandbox Code Playgroud)

这是函数的一些输出:

>>> couldRoundTo(3.934567892987, 3.9)
True
>>> couldRoundTo(3.934567892987, 3.3)
False
>>> couldRoundTo(3.934567892987, 3.93)
True
>>> couldRoundTo(3.934567892987, 3.94)
False
Run Code Online (Sandbox Code Playgroud)

据我所知,它有效.但是,考虑到我没有完全掌握有关浮点精度的问题,我害怕依赖它.有人能告诉我这是否是实现此功能的合适方式?如果没有,我怎么能改善它?

Pi *_*ort 3

有人可以告诉我这是否是实现此功能的合适方法?

这取决于。如果给定函数不精确等于通常直接从十进制到二进制浮点转换获得的值,则其行为将b令人惊讶

例如:

>>> print(0.1, 0.2/2, 0.3/3)
0.1 0.1 0.1
>>> couldRoundTo(0.123, 0.1)
True
>>> couldRoundTo(0.123, 0.2/2)
True
>>> couldRoundTo(0.123, 0.3/3)
False
Run Code Online (Sandbox Code Playgroud)

这会失败,因为 的计算结果与和(and )0.3 / 3的表示形式略有不同。0.10.2 / 2round(0.123, 1)

如果没有,我该如何改进?

经验法则:如果您的计算以任何方式特别涉及十进制数字,只需使用Decimal, 即可避免所有有损的以 2 为基数的往返。

特别是,Decimal包含一个名为的帮助程序quantize,使这个问题变得非常简单:

from decimal import Decimal

def roundable(a, b):
    a = Decimal(str(a))
    b = Decimal(str(b))
    return a.quantize(b) == b
Run Code Online (Sandbox Code Playgroud)