【问题标题】:How to fix incorrect decimal places of a multiplication result如何修复乘法结果的不正确小数位
【发布时间】:2019-06-03 18:42:58
【问题描述】:

以下计算有问题:

>>> print(float('32.31') * 1e9)
32310000000.000004

我需要这个结果是32310000000.0(没有错误的小数位)。直接使用浮点数时也会出现这种情况:

>>> print(32.31 * 1e9)
32310000000.000004

有没有办法避免错误的小数位?分析字符串并舍入到小数位数不是首选解决方案。

非常感谢。

注意:以下工作正常:

>>> print(32.32 * 1e9)
32320000000.0

所以我很高兴在测试过程中发现了上述问题。

编辑:感谢您的快速回答!对不起,我错过了一个重要的点。当结果小于一时,该方法也必须有效,例如:

32.31 * 1e-9

...在这种情况下我不能使用round(32.31 * 1e-9, 1)

【问题讨论】:

    标签: python string floating-point decimal


    【解决方案1】:

    避免您的问题的一种方法是使用 decimal 模块,该模块以 10 为基数,因此可以像人类一样工作(如果我们更快的话)。

    from decimal import Decimal
    value = float(Decimal('32.31') * Decimal(1e9))
    

    这会产生你想要的值,

    32310000000.0
    

    另一种方法是使用fractions 模块,它适用于精确值:

    from fractions import Fraction
    value = float(Fraction('32.31') * Fraction(1e9))
    

    请注意,在这两种方法中,我们都必须转换 1e9 而不仅仅是十进制值。使用1e9作为浮点数将中间值转换为浮点数,再次弹出逼近问题。在任何一种方法中,您都可以放弃对浮点类型的最终转换,并继续使用DecimalFraction 值。这些方法中的任何一种都比使用浮点类型慢一些:您以牺牲速度为代价获得准确性。在某些情况下,速度降低可能很重要。


    关于您对问题的编辑:在我的任何一种方法中使用值 1e-9 仍然会产生您想要的结果,即值 3.231e-08

    【讨论】:

    • 非常感谢! :) Fraction 方法解决了我的问题,我的所有单元测试都通过了!
    【解决方案2】:

    如果您只想打印一个小数位,您可以使用round,指定您想要的小数点后的数字,在本例中为 1

    print(round(float('32.31') * 1e9, 1))
    # 32310000000.0
    

    【讨论】:

      【解决方案3】:

      这是由浮点数的二进制尾数的表示限制引起的。 32.31 不能用二的幂除来表示。如果您知道您的值将始终是整数(或已知的小数位数),您可以使用round()int(round()) 来规避限制。

      【讨论】:

        【解决方案4】:

        我假设您使用的是 Python 3。

        如果您只关心打印的结果,请使用字符串格式:

        print("{r:1.2f}".format(r=32.31 * 1e9))
        

        另一种方法是使用旧的格式化语法:

        print("%1.1f" % (32 * 1e9))
        

        我更喜欢第一个,但任何一个都可以。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-04-15
          • 1970-01-01
          • 2023-03-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多