python - 如何避免浮点运算问题?

标签 python python-3.x floating-accuracy

Python(以及几乎任何其他东西)在处理 float 时都有已知的局限性(提供了很好的概述 here)。

虽然文档中对问题进行了很好的描述,但它避免提供任何修复方法。带着这个问题,我正在寻求一种或多或少稳健的方法来避免如下情况:

print(math.floor(0.09/0.015))   # >> 6
print(math.floor(0.009/0.0015)) # >> 5

print(99.99-99.973) # >> 0.016999999999825377
print(.99-.973)     # >> 0.017000000000000015

var = 0.009
step = 0.0015
print(var < math.floor(var/step)*step+step) # False
print(var < (math.floor(var/step)+1)*step)  # True

与此 question 中的建议不同,他们的解决方案无助于解决诸如 next peace of code randomly failing 之类的问题:

  total_bins = math.ceil((data_max - data_min) / width)  # round to upper
  new_max = data_min + total_bins * width
  assert new_max >= data_max 
  # fails. because for example 1.9459999999999997 < 1.946

最佳答案

如果您处理离散数量,请使用 int

有时人们会在绝对不应该使用的地方使用float。如果您正在计数某事(例如世界上的汽车数量)而不是测量某事(例如每天使用多少汽油), float 可能是错误的选择。货币是 float 经常被滥用的另一个例子:如果您将银行账户余额存储在数据库中,它实际上不是 123.45 美元,而是 12345 美分。 (但也请参阅下面关于 Decimal 的内容。)

其余大部分时间,使用float

float 是通用的。它们非常准确;它们只是不能表示某些分数,就像有限小数不能表示数字 1/3。 float 通常适用于测量有误差条的任何类型的模拟量:长度、质量、频率、能量——如果不确定性在 2^(-52) 或更大的数量级,则可能没有好的 不使用 float 的原因。

如果您需要人类可读的数字,请使用 float 但对其进行格式化。

“这个数字看起来很奇怪”是不使用 float理由。但这并不意味着您必须以任意精度显示数字。一个只有三位有效数字的数,如果是19.99909997918947,格式化成小数点后一位就完事了。

>>> print('{:0.1f}'.format(e**pi - pi))
20.0

如果您需要精确的十进制表示,请使用Decimal

Sraw's answer指的是 decimal 模块,它是标准库的一部分。我已经提到货币是一个离散量,但您可能需要对并非所有数字都是离散的货币量进行计算,例如计算利息。如果您正在为会计系统编写代码,就会有一些规则说明何时应用舍入以及各种计算的精度如何,这些规范将以小数位表示。在这种情况和其他情况下,小数表示法是问题规范所固有的,您需要使用小数类型。

>>> from decimal import Decimal
>>> rate = Decimal('0.0345')
>>> principal = Decimal('3412.65')
>>> interest = rate*principal
>>> interest
Decimal('117.736425')
>>> interest.quantize(Decimal('0.01'))
Decimal('117.74')

但最重要的是,使用在上下文中有意义的数据类型和操作。

您的几个示例使用了math.floor,它采用float 并去掉了小数部分。在您应该使用 math.floor 的任何情况下,浮点错误都无关紧要。 (如果您想四舍五入到最接近的整数,请改用 round。)是的,从数学的角度来看,有一些方法可以使用会产生错误结果的浮点运算。但现实世界的数量通常属于以下类别之一:

  1. 精确,因此不应放在 float 中;
  2. 不精确的程度远远超过可能累积的浮点错误。

作为一名程序员,了解您正在处理的数量并选择合适的数据类型是您工作的一部分。所以 float 没有“修复”,因为真的没有“问题”——只是人们对错误的东西使用了错误的类型。

关于python - 如何避免浮点运算问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46699651/

相关文章:

python - 附加到特定对象的属性,其中对象存储在字典中

python - 如何搜索文件中的值并替换

python - Python 3 中的冒泡排序

python - 当另一个线程处于事件状态时,为什么不在全局对象上调用__del__?

python - 是否可以强制 float 的指数或尾数匹配另一个 float (Python)?

python - 如何从项目数量可能不同的列表创建增量变量。 python 3

Python以编程方式将尾随逗号添加到元组的末尾

python - 使用 Python 3 捕获 192 kHz 音频

python - Python 中的浮点值与记录值

java - 非整数 ULP 错误?