我希望a四舍五入到13.95。我试过用圆形,但我得到:

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

有关标准库Decimal类的类似问题,请参阅How can I format a Decimal to always show 2 Decimal places?。


当前回答

要将一个数字舍入为一个分辨率,最好的方法是以下方法,该方法可以适用于任何分辨率(两个小数或甚至其他步长为0.01):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0

其他回答

对于原始Python:

对于浮点到字符串转换的2个小数点:

a = 13.949999999999999
format(a, '.2f')

对于浮点到浮点转换的2个小数点:

a = 13.949999999999999
round(float(a), 2)
or
float(format(a, '.2f'))

Python教程有一个名为“浮点算术:问题和限制”的附录。阅读它。它解释了正在发生的事情以及为什么Python做得最好。它甚至有一个与您的示例相匹配的示例。让我引用一点:

>>> 0.10.10000000000000001您可能会尝试使用round()函数将其切回单个您期望的数字。但这并不意味着差异:>>>圆形(0.1,1)0.10000000000000001问题是二进制文件为“0.1”存储的浮点值已经是最好的二进制了接近1/10,因此尝试再圆一次也不能让它变得更好:它已经很好了。另一个结果是,由于0.1不是十分之一,加十0.1的值可能不会产生精确的结果1.0,或者:>>>总和=0.0>>>对于范围(10)中的i:…总和+=0.1...>>>总和0.99999999999999989

解决问题的另一种方法是使用十进制模块。

TLDR;)

Python 3.1已经明确解决了输入和输出的舍入问题,该修复程序也被移植到Python 2.7.0。

舍入数字可以在浮点数和字符串之间来回转换:str->float()->repr()->float)。。。或Decimal->float->str->Decimal

>>> 0.3
0.3
>>> float(repr(0.3)) == 0.3
True

存储不再需要十进制类型。

算术运算的结果必须再次舍入,因为舍入误差可能累积的误差比解析一个数字后可能累积的更大。这不是通过改进的repr()算法解决的(Python>=3.1,>=2.7.0):

>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1, 0.2, 0.3
(0.1, 0.2, 0.3)

在Python<2.7x和<3.1中,输出字符串函数str(float(…))被舍入为12个有效数字,以防止类似于未固定repr()输出的无效数字过多。在减去非常相似的数字之后,这仍然是不够的,并且在其他操作之后,它被舍入得太多。Python 2.7和3.1使用相同长度的str(),尽管repr()是固定的。一些旧版本的Numpy也有过多的无效数字,即使是固定的Python。当前Numpy是固定的。Python版本>=3.2中str()和repr()函数的结果相同,Numpy中也有类似函数的输出。


Test

import random
from decimal import Decimal
for _ in range(1000000):
    x = random.random()
    assert x == float(repr(x)) == float(Decimal(repr(x)))  # Reversible repr()
    assert str(x) == repr(x)
    assert len(repr(round(x, 12))) <= 14         # no excessive decimal places.

文档

请参阅发行说明Python 2.7-其他语言更改第四段:

在大多数平台上,浮点数和字符串之间的转换现在都可以正确舍入。这些转换发生在许多不同的地方:浮点和复数上的str();浮点和复杂的构造函数;数字格式;使用marshall、pickle和json模块对浮点数和复数进行序列化和反序列化;Python代码中浮点和虚文本的解析;以及十进制到浮点转换。与此相关,浮点数x的repr()现在返回一个基于最短十进制字符串的结果,该字符串保证在正确舍入(使用舍入半到偶数模式)下舍入回x。之前它给出了一个基于将x舍入到17位小数的字符串。

相关问题


更多信息:Python 2.7之前的float格式类似于当前的numpy.float64。两种类型使用相同的64位IEEE 754双精度和52位尾数。一个很大的区别是np.fat64.__repr_经常使用过量的十进制数字进行格式化,因此不会丢失任何位,但在13.949999999999999和13.95000000000001之间不存在有效的IEEE 754数字。结果不好,转换repr(float(number_as_string))不能用numpy可逆。另一方面:浮动__repr_的格式使得每个数字都很重要;序列是无间隙的,并且转换是可逆的。简单地说:如果您可能有一个numpy.float64数字,请将其转换为普通浮点,以便为人类而不是数字处理器格式化,否则Python 2.7+就不需要更多了。

要计算,我使用函数截断值也许对你有帮助

import math


def truncate(number, digits) -> float:
    stepper = pow(10.0, digits)
    return math.trunc(stepper * number) / stepper


print(truncate((0.1 + 0.2), 2))

内置round()在Python 2.7或更高版本中运行良好。

例子:

>>> round(14.22222223, 2)
14.22

查看文档。