2082

我想a四舍五入到13.95

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

round功能无法按我预期的方式工作。

4

32 回答 32

2056

您遇到了浮点数的老问题,即并非所有数字都可以精确表示。命令行只是向您显示内存中的完整浮点形式。

使用浮点表示,您的四舍五入版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以 2 的幂,因此 13.95 将以类似于 125650429603636838/(2**53) 的方式表示。

双精度数的精度为 53 位(16 位),而普通浮点数的精度为 24 位(8 位)。Python 中的浮点类型使用双精度来存储值。

例如,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

如果您只在小数点后两位(例如,显示货币价值),那么您有几个更好的选择:

  1. 使用整数并以美分而不是美元存储值,然后除以 100 以转换为美元。
  2. 或者使用像decimal这样的定点数。
于 2009-01-18T18:23:53.870 回答
722

有新的格式规范,String Format Specification Mini-Language

您可以执行以下操作:

"{:.2f}".format(13.949999999999999)

注1:上面返回一个字符串。为了获得浮动,只需包装float(...)

float("{:.2f}".format(13.949999999999999))

注意2:包装float()不会改变任何东西:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
于 2011-06-30T18:53:13.480 回答
366

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

例子:

>>> round(14.22222223, 2)
14.22

查看文档

于 2016-12-31T10:51:43.137 回答
190

Nobody here seems to have mentioned it yet, so let me give an example in Python 3.6's f-string/template-string format, which I think is beautifully neat:

>>> f'{a:.2f}'

It works well with longer examples too, with operators and not needing parens:

>>> print(f'Completed in {time.time() - start:.2f}s')
于 2017-12-12T14:45:44.850 回答
169

我觉得最简单的方法是使用format()函数。

例如:

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

13.95

这会产生一个浮点数作为四舍五入到小数点后两位的字符串。

于 2015-01-25T22:26:58.153 回答
99

大多数数字不能用浮点数精确表示。如果你想对数字进行四舍五入,因为这是你的数学公式或算法需要的,那么你想使用round。如果您只想将显示限制在某个精度,那么甚至不要使用 round 并将其格式化为该字符串。(如果你想用一些替代的舍入方法来显示它,并且有很多,那么你需要混合这两种方法。)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

最后,虽然也许最重要的是,如果你想要精确的数学,那么你根本不需要浮点数。通常的例子是处理金钱并将“美分”存储为整数。

于 2009-01-18T18:40:03.273 回答
99

利用

print"{:.2f}".format(a)

代替

print"{0:.2f}".format(a)

因为后者在尝试输出多个变量时可能会导致输出错误(见注释)。

于 2017-08-04T08:40:49.913 回答
70

试试下面的代码:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
于 2013-08-26T06:46:25.387 回答
67

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

Decimal存储不再需要类型。

算术运算的结果必须再次四舍五入,因为四舍五入的误差可能会比解析一个数字后累积的误差更大。改进的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 中也有类似函数的输出。


测试

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 - Other Language Changes第四段:

浮点数和字符串之间的转换现在在大多数平台上都可以正确舍入。这些转换发生在许多不同的地方:浮点数和复数上的 str();float 和 complex 构造函数;数字格式;marshal使用,picklejson模块对浮点数和复数进行序列化和反序列化;解析 Python 代码中的浮点数和虚数文字;和小数到浮点数的转换。

与此相关,浮点数 x的repr()现在返回基于最短十进制字符串的结果,该字符串保证在正确舍入(使用半舍入到偶数舍入模式)下舍入为 x。以前它给出了一个基于将 x 舍入为 17 位十进制数字的字符串。

相关问题


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

于 2016-01-31T18:33:53.200 回答
59
float_number = 12.234325335563
round(float_number, 2)

这将返回;

12.23

解释:

round 函数有两个参数;要四舍五入的数字和要返回的小数位数。这里我返回了 2 个小数位。

于 2020-11-04T13:08:39.133 回答
56

您可以修改输出格式:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
于 2009-01-18T18:31:50.123 回答
55

对于 Python < 3(例如 2.6 或 2.7),有两种方法可以做到这一点。

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

但请注意,对于 3 以上的 Python 版本(例如 3.2 或 3.3),选项二是首选

有关选项二的更多信息,我建议使用 Python 文档中关于字符串格式的链接。

有关选项一的更多信息,此链接就足够了,并且包含有关各种标志的信息

参考:将浮点数转换为一定精度,然后复制为字符串

于 2013-12-11T06:37:46.813 回答
41

您可以使用格式运算符在 python 中将值四舍五入到小数点后 2 位:

print(format(14.4499923, '.2f')) // output is 14.45
于 2019-02-06T06:37:51.470 回答
31

在 Python 2.7 中:

a = 13.949999999999999
output = float("%0.2f"%a)
print output
于 2018-03-16T10:49:21.650 回答
26

正如@Matt 指出的那样,Python 3.6 提供了 f-strings,它们也可以使用嵌套参数

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

这将显示result: 2.35

于 2018-02-01T09:43:03.657 回答
25

我们有多种选择:选项1:

x = 1.090675765757
g = float("{:.2f}".format(x))
print(g)

选项 2:内置的 round() 支持 Python 2.7 或更高版本。

x = 1.090675765757
g =  round(x, 2)
print(g)
于 2020-09-30T04:31:37.360 回答
24

The Python tutorial has an appendix called Floating Point Arithmetic: Issues and Limitations. Read it. It explains what is happening and why Python is doing its best. It has even an example that matches yours. Let me quote a bit:

>>> 0.1
0.10000000000000001

you may be tempted to use the round() function to chop it back to the single digit you expect. But that makes no difference:

>>> round(0.1, 1)
0.10000000000000001

The problem is that the binary floating-point value stored for “0.1”</code> was already the best possible binary approximation to 1/10, so trying to round it again can’t make it better: it was already as good as it gets.

Another consequence is that since 0.1 is not exactly 1/10, summing ten values of 0.1 may not yield exactly 1.0, either:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

One alternative and solution to your problems would be using the decimal module.

于 2009-01-19T02:05:53.797 回答
15

使用 Decimal 对象和 round() 方法的组合。

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')
于 2019-06-01T02:04:26.543 回答
13

它正在做你告诉它做的事情并且工作正常。阅读有关浮点混淆的更多信息,也许可以尝试使用十进制对象。

于 2009-01-18T18:33:45.160 回答
9
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

结果:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
于 2018-12-21T07:55:13.967 回答
7

为了修复 Python 和 JavaScript 等类型动态语言中的浮点,我使用了这种技术

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

您还可以使用十进制,如下所示:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
于 2014-04-02T20:08:01.827 回答
7

像这样的 lambda 函数怎么样:

arred = lambda x,n : x*(10**n)//1/(10**n)

这样你就可以这样做:

arred(3.141591657,2)

并得到

3.14
于 2019-04-28T00:45:47.307 回答
6

很简单,比如 1,2,3:

  1. 使用十进制模块进行快速正确舍入的十进制浮点运算:

    d=十进制(10000000.0000009)

实现四舍五入:

   d.quantize(Decimal('0.01'))

将导致Decimal('10000000.00')

  1. 使上述干燥:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

或者

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. 赞成这个答案:)

PS:批评他人:格式化不是四舍五入。

于 2019-01-29T17:43:58.700 回答
6
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54

于 2017-09-04T12:38:06.983 回答
4

这是使用格式功能的简单解决方案。

float(format(num, '.2f'))

注意:我们将数字转换为浮点数,因为格式方法返回字符串。

于 2021-07-29T05:49:36.590 回答
3

要将数字四舍五入为分辨率,最好的方法是以下一种,它可以用于任何分辨率(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
于 2015-08-26T09:17:52.593 回答
3

我看到的答案不适用于 float(52.15) 案例。经过一些测试,有我正在使用的解决方案:

import decimal
        
def value_to_decimal(value, decimal_places):
    decimal.getcontext().rounding = decimal.ROUND_HALF_UP  # define rounding method
    return decimal.Decimal(str(float(value))).quantize(decimal.Decimal('1e-{}'.format(decimal_places)))

('value' 到 float 和 string 的转换非常重要,这样,'value' 的类型可以是 float、decimal、integer 或 string!)

希望这对任何人都有帮助。

于 2020-07-22T13:50:47.437 回答
3

lambda x,n:int(x*10^n+.5)/10^n 多年来为我工作了很多语言。

于 2019-12-17T02:43:53.993 回答
2

如果要处理金钱,请使用python十进制模块

from decimal import Decimal, ROUND_HALF_UP

# amount can be integer, string, tuple, float, or another Decimal object
def to_money(amount) -> Decimal:
    money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
    return money
于 2020-11-20T22:00:48.580 回答
0

简单的解决方案在这里

value = 5.34343
rounded_value = round(value, 2) # 5.34
于 2022-02-05T14:23:28.027 回答
-1

只需使用此函数并将字节作为输入传递给它:

def getSize(bytes):
    kb = round(bytes/1024, 4)
    mb = round(kb/1024, 4)
    gb = round(mb/1024, 4)
    if(gb > 1):
        return str(gb)+" GB"
    elif(mb > 1):
        return str(mb)+" MB"
    else:
        return str(kb)+" KB"

这是我可以将数据大小从字节动态转换为 KB、MB 或 GB 的最简单方法

于 2021-09-09T08:01:25.697 回答
-16

我使用的方法是字符串切片。它相对快速和简单。

首先,将浮点数转换为字符串,选择您想要的长度。

float = str(float)[:5]

在上面的单行中,我们将值转换为字符串,然后只保留字符串的前四个数字或字符(包括在内)。

希望有帮助!

于 2015-12-31T08:05:56.970 回答