限制浮点数到两个小数点

我想要a四舍五入到13.95

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

round函数不能按照我的预期工作。

你遇到了所有数字都不能表示的浮点数的老问题。 命令行仅显示内存中的完整浮点格式。 在浮点上,你的四舍五入的版本是相同的数字。 由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以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("{0:.2f}".format(a)) 13.95 >>> print("{0:.2f}".format(round(a,2))) 13.95 >>> print("{0:.15f}".format(round(a,2))) 13.949999999999999 

如果你在货币后只有两位小数,那么你有几个更好的select使用整数和商店价值以美分,然后除以100转换为美元。 或者使用像十进制这样的定点数字

有新的格式规格, string格式规范迷你语言

你可以这样做:

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

请注意 ,上述返回一个string。 为了得到浮动,只需用float(...)

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

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

 >>> x = 13.949999999999999999 >>> x 13.95 >>> g = float("{0:.2f}".format(x)) >>> g 13.95 >>> x == g True >>> h = round(x, 2) >>> h 13.95 >>> x == h True 

大多数数字不能完全表示在浮动。 如果你想将数字四舍五入,因为这就是你的math公式或algorithm所需要的,那么你想要使用一轮。 如果你只是想限制显示的精确度,那么就不要使用round,而只是把它格式化为string。 (如果你想用一些交替的舍入方法显示它,并且有很多,那么你需要混合两种方法。)

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

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

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

例如:

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

这将产生一个浮点数作为一个string四舍五入到两个小数点。

内置的round()在Python 3中工作得很好 。 例:

 >>> round(14.22222223, 2) 14.22 

检查文档 。

尝试下面的代码:

 >>> a = 0.99334 >>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up >>> print a 0.99 

用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) 

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

有关选项2的更多信息,我build议从python文档的string格式的链接。

而对于选项一的更多信息, 这个链接就足够了,并有各种标志的信息。

参考: 将浮点数转换为一定的精度,然后复制到string

你可以做的是修改输出格式:

 >>> a = 13.95 >>> a 13.949999999999999 >>> print "%.2f" % a 13.95 

tldr)

input/输出的舍入问题已经被Python 2.7.0彻底解决了

  import random for x in iter(random.random, None): # verify FOREVER fixed :-) assert float(repr(x)) == x # Reversible repr() conversion assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round if x >= 0.1: # Implicit rounding to 12 significant digits assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors y = 1000 * x # Decimal type is excessive for shopping assert str(x) == repr(round(x, 12 - 3)) # in the supermaket with Python 2.7+ :-) 

文档

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

浮点数和string之间的转换现在可以在大多数平台上正确舍入 。 这些转换发生在许多不同的地方:str()浮点数和复数; 浮动和复杂的构造函数; 数字格式; 使用marshal,pickle和json模块序列化和反序列化浮点数和复数; 在Python代码中parsingfloat和imaginary文字; 和十进制到浮点数转换。

与此相关,浮点数x的repr()现在返回基于最小十进制string的结果,该string保证在正确的舍入(舍入到半舍入舍入模式)下返回到x 。 以前它给出了一个基于四舍五入到十七个十进制数字的string。

相关的问题


编辑 – 更多信息:: Python 2.7之前的float格式与当前的numpy.float64类似。 这两种types使用相同的64位IEEE 754双精度与52位mantisa。 一个很大的区别是, np.float64.__repr__经常用一个十进制数来形成,所以没有位可以丢失,但是在13.949999999999999和3.950000000000001之间不存在有效的IEEE 754号码,结果是不好的,转换repr(float(number_as_string))是不可逆的。 另一方面: float.__repr__是格式化的,因此每个数字都很重要,序列没有间隙,转换是可逆的。 简单地说:如果你可能有一个numpy.float64数字,把它转换成普通的float值,以便为人类而不是数字处理器格式化,否则在Python 2.7+中不需要更多。

python教程有一个附录,名为: 浮点运算:问题和局限性 。 阅读。 它解释了正在发生的事情以及为什么python正在尽力而为。 它甚至有一个与你相匹配的例子。 让我引用一下:

 >>> 0.1 0.10000000000000001 

您可能会试图使用round()函数将其切回到您期望的单个数字。 但是这没有什么区别:

 >>> round(0.1, 1) 0.10000000000000001 

问题是存储为“0.1”的二进制浮点值已经是1/10的最好可能的二进制近似值,所以再次尝试四舍五入变得不可能:它已经达到了它的水平。

另一个结果是,由于0.1不完全是1/10 ,因此总计十个0.1值可能不会恰好产生1.0 ,或者:

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

您的问题的一个替代scheme和解决scheme将使用decimal模块。

它正在按照你所说的去做,并正确地工作。 请阅读有关浮点混淆的更多信息,也可以尝试使用Decimal对象。

为了修正dynamic语言(如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) #result in 6 precision -> Decimal('0.142857') getcontext().prec = 28 Decimal(1) / Decimal(7) #result in 28 precision -> Decimal('0.1428571428571428571428571429') 

使用

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

代替

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

因为后者可能会在尝试输出多个variables时引发错误

要将一个数字舍入为一个分辨率,最好的方法是下面的一个,它可以使用任何分辨率(小数点后两位为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 
 orig_float = 232569 / 16000.0 

14.5355625

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

14.54

我使用的方法是string切片。 这相对快捷简单。

首先,将float转换为一个string,select你想要的长度。

 float = str(float)[:5] 

在上面的单行中,我们将该值转换为一个string,然后将该string保留为其前四位数字或字符(包括)。

希望有所帮助!