我希望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
如果您只有两位小数,那么您有几个更好的选择:1)使用整数并以美分存储值,而不是美元,然后除以100转换为美元.2)或使用十进制的固定点数.
有新的格式规范,字符串格式规范迷你语言:
您可以这样做:
"{0:.2f}".format(13.949999999999999)
请注意,上面返回一个字符串.为了得到浮点数,只需用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
内置round()
在Python 2.7或更高版本中运行良好.
例:
>>> round(14.22222223, 2) 14.22
查看文档.
我觉得最简单的方法是使用该format()
功能.
例如:
a = 13.949999999999999 format(a, '.2f') 13.95
这会产生一个浮点数作为一个四舍五入到两个小数点的字符串.
大多数数字不能用浮点数精确表示.如果你想要对数字进行舍入,因为这是你的数学公式或算法所需要的,那么你想要使用round.如果您只想将显示限制到一定的精度,那么甚至不要使用round,只需将其格式化为该字符串即可.(如果你想用一些替代的舍入方法显示它,并且有吨,那么你需要混合这两种方法.)
>>> "%.2f" % 3.14159 '3.14' >>> "%.2f" % 13.9499999 '13.95'
最后,虽然也许最重要的是,如果你想要精确的数学,那么你根本不需要花车.通常的例子是处理货币并将"美分"存储为整数.
使用
print"{:.2f}".format(a)
代替
print"{0:.2f}".format(a)
因为后者在尝试输出多个变量时可能会导致输出错误(请参阅注释).
请尝试以下代码:
>>> 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)
但请注意,对于3以上的Python版本(例如3.2或3.3),选项2是首选.
有关选项二的更多信息,我建议使用Python文档中的字符串格式链接.
有关选项一的更多信息,此链接就足够了,并且有关于各种标志的信息.
参考:将浮点数转换为特定精度,然后复制到字符串
输入/输出的舍入问题已由Python 2.7.0和3.1明确解决.
无限测试:
import random from decimal import Decimal for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-) assert float(repr(x)) == x # Reversible repr() conversion. assert float(Decimal(repr(x))) == x 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(y) == repr(round(y, 12 - 3)) # in a supermaket with Python 2.7+ :-)
请参阅发行说明Python 2.7 - 其他语言更改第四段:
现在,在大多数平台上,浮点数和字符串之间的转换已正确舍入.这些转换发生在许多不同的地方:浮点数上的str()和复数; 浮动和复杂的构造函数; 数字格式; 序列化使用和反序列化浮子和复数
str -> float() -> repr() -> float() ...
,Decimal -> float -> str -> Decimal
和str()
模块; 在Python代码中解析float和imaginary文字; 和十进制到浮点转换.与此相关,浮点数x 的repr()现在返回基于最短十进制字符串的结果,该最小十进制字符串保证在正确的舍入下舍入到x(具有舍入到半舍入到舍入模式).以前它给出了一个基于舍入x到17个十进制数字的字符串.
相关问题
更多信息::marshal
Python 2.7之前的格式与当前类似pickle
.两种类型都使用相同的64位IEEE 754双精度和52位尾数.一个很大的区别是json
经常使用过多的十进制数格式化,因此不会丢失任何位,但13.949999999999999和13.950000000000001之间不存在有效的IEEE 754编号.结果不好,转换float
不可逆.另一方面:numpy.float64
格式化,以便每个数字都很重要; 序列没有间隙,转换是可逆的.简单地说:如果您可能有一个numpy.float64数字,请将其转换为普通浮点数,以便为人类而不是数字处理器进行格式化,否则Python 2.7+不再需要它.
您可以修改输出格式:
>>> a = 13.95 >>> a 13.949999999999999 >>> print "%.2f" % a 13.95
您可以使用格式运算符将值四舍五入到python中的小数点后2位:
print(format(14.4499923, '.2f')) // output is 14.45
这里似乎没有人提到它,所以让我举一个Python 3.6的f-string/template-string格式的例子,我觉得它很漂亮:
>>> f'{a:.2f}'
它也可以用更长的例子,运算符而不需要parens:
>>> print(f'Completed in {time.time() - start:.2f}s')
在Python 2.7中:
a = 13.949999999999999 output = float("%0.2f"%a) print output
Python教程有一个名为Floating Point Arithmetic的附录:问题和限制.阅读.它解释了发生了什么以及为什么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
解决问题的另一种方法是使用该decimal
模块.
正如@Matt指出的那样,Python 3.6提供了f字符串,它们也可以使用嵌套参数:
value = 2.34558 precision = 2 width = 4 print(f'result: {value:{width}.{precision}f}')
将显示 result: 2.35
它正在完成你告诉它要做的事情并且正常工作.阅读有关浮点混淆的更多信息,也可以尝试使用十进制对象.
为了修复类型动态语言(如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
您还可以使用Decimal,如下所示:
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')
结合使用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')
orig_float = 232569 / 16000.0
14.5355625
short_float = float("{:.2f}".format(orig_float))
14.54
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'