【问题标题】:Doing arithmetic with up to two decimal places in Python?在 Python 中进行最多两位小数的算术运算?
【发布时间】:2010-05-04 00:03:27
【问题描述】:

我想减去 Python 中的两个浮点数,即

v1 = float(value1)
v2 = float(value2)
diff = v1 - v2

我希望将“差异”计算到小数点后两位,即使用 v1 的 %.2f 和 v2 的 %.2f 计算它。我怎样才能做到这一点?我知道如何将 v1 和 v2 打印到小数点后两位,但不知道如何进行这样的算术运算。

我试图避免的特定问题是这个。假设:

v1 = 0.982769777778
v2 = 0.985980444444
diff = v1 - v2

然后我打印到以下文件:

myfile.write("%.2f\t%.2f\t%.2f\n" %(v1, v2, diff))

然后我会得到输出:0.98 0.99 0.00,表明 v1 和 v2 之间没有区别,即使打印结果表明存在 0.01 的差异。我该如何解决这个问题?

谢谢。

【问题讨论】:

  • 我可以通过简单地做:round(v1, 2) 和 round(v2, 2) 来做到这一点吗?如果可能的话,我想避免像十进制这样的额外库。
  • 为什么要计算只有 2 个有效数字?以最大精度进行计算并在最后格式化结果有什么问题?您是否混淆了有效数字和小数位?
  • 这就是问题所在。如果我在不四舍五入的情况下计算 diff,那么我使用“%.2f”将结果打印到文件中,这意味着我可以将 v1 = 0.982769777778 打印为“0.98”和 v2 = 0.985980444444 打印为“0.99”,而diff 打印为“0.00”,这是一种误导。这就是我想要解决的问题。有什么想法吗?

标签: python floating-point numpy scipy


【解决方案1】:

您在评论中说您不想使用decimal,但听起来您确实应该在这里使用。请注意,它不是“额外库”,因为它是 Python v2.4 以来默认提供的,您只需要import decimal。当您想要显示值时,您可以使用Decimal.quantize 将数字四舍五入到小数点后 2 位以进行显示,然后取所得小数的差。

>>> v1 = 0.982769777778
>>> v2 = 0.985980444444
>>> from decimal import Decimal
>>> d1 = Decimal(str(v1)).quantize(Decimal('0.01'))
>>> d2 = Decimal(str(v2)).quantize(Decimal('0.01'))
>>> diff = d2 - d1
>>> print d1, d2, diff
0.98 0.99 0.01

【讨论】:

  • 您能解释一下如何在这里使用十进制来获得连贯的打印,同时仍然具有精确的算术吗?圆形解决方案有什么问题?
  • 这没有原始的、更简单、更高效的代码那么精确。
  • 再次检查你的飞镖图;我的意思是精确。 ;)
  • 好吧……很公平——我错了。有2倍的差异。但是相同的数量级......:-P
【解决方案2】:

我以前用过穷人的定点。本质上,使用整数,将所有数字乘以 100,然后在打印之前将它们除以 100。

最近在Slashdot 上有一篇关于类似问题的好帖子。

【讨论】:

    【解决方案3】:

    我发现圆形是一个不错的选择。

    a = 2.000006
    b = 7.45001
    c = b - a
    print(c) #This gives 5.450004
    print(round(c, 2)) ##This gives 5.45
    

    【讨论】:

      【解决方案4】:

      float 类型的问题是您无法真正控制计算 的精度。 float 类型让硬件进行计算,这通常以最有效的方式进行。因为浮点数(像大多数机器优化的东西一样)是二进制的,而不是十进制的,所以强制这些计算具有特定精度十进制并不简单(或有效)。有关相当中肯的解释,请参阅the last chapter of the Python tutorial。您可以对浮点数做的最好的事情是对计算结果进行四舍五入(最好只是在格式化它们时。)

      为了控制实际计算和精度(以十进制表示,不少于),您应该考虑改用 decimal 模块中的小数。它使您可以更好地控制几乎所有内容,尽管这样做会以速度为代价。

      【讨论】:

        【解决方案5】:

        “两个有效数字”是什么意思? Python float 有大约 15 个 sigfigs,但它确实存在表示错误和舍入错误(decimal.Decimal 也是如此。)http://docs.python.org/tutorial/floatingpoint.html 可能对您来说是一本有趣的读物,以及关于浮点数的大量资源.

        float 通常具有表示实数的正确精度,例如物理测量值:重量、距离、持续时间、温度等。如果要打印出某种显示浮点数的方式,请使用字符串格式按照你的建议。

        如果您想准确表示固定精度的事物,您可能需要使用整数。您必须自己记录小数位,但这通常并不难。

        decimal.Decimal 被推荐的太多了。它可以调整到特定的、高于浮点数的精度,但这很少需要;我认为我从未见过有人应该使用decimal.Decimal 的原因。 decimal.Decimal 让您可以精确地表示十进制数字并控制四舍五入的工作方式,这使其适合在某些情况下表示货币。

        【讨论】:

        • 我了解计算精度和显示精度之间的区别,即您输出到文件的精度。我上面的例子表明这可能会导致误导性的输出。我的问题是:我怎样才能解决这个问题?十进制解是什么?
        • @user248237,如果百分之一是你的重要位,那么你不应该关心你的答案是百分之一。这不是特定于浮点数,这是我们在表示我们正在处理的近似数字时更普遍地处理的事情。这里的“0.01”会比“0.00”更不真实(会有更大的错误),所以显示它并不是真正的正确的事情。
        • 当我说我们只是在处理不准确的数字显示时让这种情况发生,我并不是说我们在马虎或懒惰时会这样做;例如,在 Excel 或 OOCalc 中输入您的测试数字,然后将显示显示为小数点后两位——同样的小问题也会发生。
        【解决方案6】:

        您可以使用不同的格式字符串对其进行格式化。试试'%.2g''%.2e'。任何体面的C/C++ reference 都会描述不同的说明符。 %.2e 将值格式化为指数符号中的三位有效数字 - 2 表示小数点后两位数和小数点前一位数。 %.2g 将产生%.2f%.2e,具体取决于哪一个会在最少的空间中产生两位有效数字。

        >>> v1 = 0.982769777778
        >>> v2 = 0.985980444444
        >>> print '%.2f' %v1
        0.98
        >>> print '%.2g' %v1
        0.98
        >>> print '%.2e' %v1
        9.83e-01
        >>> print '%.2g' %(v2-v1)
        0.0032
        >>> print '%.2e' %(v2-v1)
        3.21e-03
        

        【讨论】:

        • @D.Shawley:我认为 OP 希望得到 2 个小数位的结果,而不是两个有效数字。我已将问题更新为我认为的意思。
        猜你喜欢
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-26
        • 2019-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多