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

作为我编写的一些单元测试代码的一部分,我编写了以下函数。 其目的在于确定'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

以下是该函数的一些输出:

>>> couldRoundTo(3.934567892987, 3.9)
True
>>> couldRoundTo(3.934567892987, 3.3)
False
>>> couldRoundTo(3.934567892987, 3.93)
True
>>> couldRoundTo(3.934567892987, 3.94)
False

据我所知,它可以工作。 不过,考虑到我对浮点精度问题没有完全掌握,我很害怕依赖它。 有人能告诉我这是否是实现此功能的适当方式? 如果不是,我怎么能改进它?


有人能告诉我这是否是实现此功能的适当方式?

这取决于。 如果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

这是因为0.3 / 3的计算结果与0.10.2 / 2 (和round(0.123, 1) )略有不同。

如果不是,我怎么能改进它?

经验法则:如果您的计算以任何方式具体涉及小数位数,则只需使用Decimal来避免所有有损基数为2的往返操作。

特别是, Decimal包含一个称为quantize的帮助quantize ,使这个问题变得轻而易举:

from decimal import Decimal

def roundable(a, b):
    a = Decimal(str(a))
    b = Decimal(str(b))
    return a.quantize(b) == b

一种方法:

def could_round_to(a, b):
    (x, y) = map(len, str(b).split('.'))
    round_format = "%" + "%d.%df"%(x, y)
    return round_format%a == str(b) 

首先,我们取x和y的小数点前后的位数。 然后,我们构造一个格式如%x.yf 。 然后,我们提供a格式字符串。

>>> "%2.2f"%123.1234
'123.12'
>>> "%2.2f"%123.1264
'123.13'
>>> "%3.2f"%000.001
'0.00'

现在,剩下的就是比较字符串。


我担心的唯一问题是在解释浮点文字时从字符串转换为浮点(如http://docs.python.org/reference/lexical_analysis.html#floating-point-literals中所述)。 我不知道是否有任何保证,浮点文字将评估为最接近给定字符串的浮点数。 这个提到的部分是我希望得到这种保证的规范中的地方。

例如,Java对字符串文字的期望更具体。 从Double.valueOf(String)的文档:

[[]] [参数]被认为是通常的“计算机化的科学记数法”中的精确十进制值或十进制精确值; 这个确切的数值然后在概念上被转换成一个“无限精确”的二进制值,然后通过IEEE 754浮点算术常用的舍入到最近的规则进行舍入,

除非你可以在Python文档的任何地方找到这样的保证,否则你可能会很幸运,因为一些较早的浮点库(Python可能依赖它)将字符串转换为附近的浮点数,而不是最佳可用。

不幸的是,在我看来,无论是round还是float ,还是浮点规范都不会给你任何有用的保证。

链接地址: http://www.djcxy.com/p/48241.html

上一篇: Python: a could be rounded to b in the general case

下一篇: How to access a data structure from a currently running Python process on Linux?