限制浮点数到两个小数点
我想要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保留为其前四位数字或字符(包括)。
希望有所帮助!