【问题标题】:Precision of decimals in PythonPython中的小数精度
【发布时间】:2014-02-08 05:58:36
【问题描述】:

我的意思不是精确到小数点后显示多少个数字。我的意思是我试图在这个象形文字功能中使用的十进制精度,比它应该的精度低十分之一。我尝试过使用多种不同的策略,包括导入十进制模块。这是我正在尝试使用的功能。

values = [('tens', 10), ('fives', 5), ('ones', 1), ('tenths', 0.1)]

def get_digits(num):
    num = int(num * 10)
    num = float(num) / 10

    output_dict = {}
    for place, value in values:
        output_dict[place] = int(num // value)
        num = num % value

    return output_dict

使用get_digits(277.9),产生{'tens': 27, 'ones': 2, 'tenths': 8, 'fives': 1}

我需要它说{'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1}

在字典被填充后通过在十分之一上加 1 来修复它是行不通的,因为不是每个小数都输出不精确。

get_digits(277.6) 返回{'fives': 1, 'tenths': 6, 'tens': 27, 'ones': 2}

我一直在论坛上寻找答案,但没有得到答案。任何帮助将不胜感激。

【问题讨论】:

  • 这只是使用浮点数和计算机无法完美存储它们的结果。请参阅1、2。如果您想要准确性,请使用定点整数类型。
  • 那么,我只是梦想能够做我想做的事吗?
  • 如果不精确的浮点数确实是问题,那么使用 decimal.Decimal() 应该会有所帮助,因为它们精确地存储以 10 为底的数字。你也可以试试 fractions.Fraction()。
  • 不,当准确性很重要时(财务、科学等),计算机一直在使用。关键是避免使用浮点数,要么自己处理(通常通过将任何可能的小数乘以一致的 10 的幂得到整数)或使用库(例如 Python 的 decimal 库)跨度>

标签: python decimal precision


【解决方案1】:

正如我试图在 cmets 中解释的那样,问题在于您使用的是浮点数。

有关浮点的更多信息,请参阅1、2。

问题是277.9 不是实际上存储为277.9,而是“非常接近”的东西:

print('%.40f' % a)
277.8999999999999772626324556767940521240234

解决方案不是使用一些任意的启发式方法来判断数学是否略有偏差并尝试对其进行纠正。我们知道数学有点不对劲——这是浮点数给我们的恩赐和诅咒。

真正的解决方案是使用定点数学,例如 Python 的 decimal 模块。


编辑

from decimal import Decimal

values = [
    ('tens',   Decimal(10)),
    ('fives',  Decimal(5)),
    ('ones',   Decimal(1)),
    ('tenths', Decimal('0.1'))
]

def get_digits(num):
    output_dict = {}
    for place, value in values:
        output_dict[place] = int(num // value)  # Cast from Decimal to int
        num = num % value
    return output_dict

num = Decimal('277.9')
print(get_digits(num))
# {'tens': 27, 'ones': 2, 'tenths': 9, 'fives': 1}

num = Decimal('277.6')
print(get_digits(num))
#{'tens': 27, 'ones': 2, 'tenths': 6, 'fives': 1}

上面的代码和你的很相似,但是使用了 Python 的十进制模块。不需要启发式检查。该代码可以正常工作,因为小数表示准确。

【讨论】:

  • 定点数学仍然可能存在精度错误 - 如果有的话,它比浮点更容易出错。 Python的decimal模块擅长存储以10为底的数字,因为decimal的实现也是以10为底的。
  • 我同意定点可以有精度误差,但与浮点表示不同,定点表示允许用户指定精度。此外,这个问题似乎特别适合定点表示,因为它涉及以 10 为底的模运算。这些数字永远不能以浮点表示形式精确存储,但始终以定点形式精确存储(只要有足够的精度)。
  • 谢谢。这两种解释都帮助我理解了更多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
相关资源
最近更新 更多