代码之家  ›  专栏  ›  技术社区  ›  Wilduck

Python:一般情况下a可以四舍五入到b

  •  7
  • Wilduck  · 技术社区  · 16 年前

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

    据我所知,这是有效的。但是,我害怕依赖它,因为我对浮点精度的问题没有一个完美的把握。有人能告诉我这是否是实现这个功能的适当方法吗?如果没有,我该如何改进呢?

    4 回复  |  直到 16 年前
        1
  •  3
  •   Pi Delport    16 年前

    有人能告诉我这是否是实现这个功能的适当方法吗?

    要看情况而定。如果 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.1 0.2 / 2 (和 round(0.123, 1)

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

    经验法则:如果你的计算特别涉及十进制数字,只要使用 Decimal

    特别地, 十进制的 包括一个名为 quantize

    from decimal import Decimal
    
    def roundable(a, b):
        a = Decimal(str(a))
        b = Decimal(str(b))
        return a.quantize(b) == b
    
        2
  •  1
  •   dheerosaur    16 年前

    一种方法:

    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'
    

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

        3
  •  0
  •   Roland Illig    16 年前

    我唯一担心的是在解释浮点字面值时从字符串到浮点的转换(如 http://docs.python.org/reference/lexical_analysis.html#floating-point-literals 最接近给定字符串的浮点数 . 这一节提到的地方,在规范中,我会期待这样的保证。

    例如,Java对字符串文本的期望更为具体。根据 Double.valueOf(String)

    […][论据]被视为在通常的“计算机科学记数法”中代表精确的十进制值或精确的十六进制值;这个精确的数值在概念上被转换成一个“无限精确”的二进制值,然后按照ieee754浮点算术的最接近规则舍入到double类型[…]

    不幸的是,在我看来 round ,也没有 float

        4
  •  0
  •   Anurag Uniyal    16 年前

    如果你的目的是测试 round 函数将舍入到目标,则您是正确的。否则(还有什么目的?)如果你有疑问,你应该使用 decimal 模块

    推荐文章