Python 将浮点限制为两个小数点
我希望Python 将浮点限制为两个小数点,python,floating-point,rounding,precision,Python,Floating Point,Rounding,Precision,我希望a四舍五入到13.95 该函数的工作方式与我预期的不同。您遇到的是浮点数字,并非所有数字都可以精确表示。命令行只是显示内存中的完整浮点形式 使用浮点表示法时,舍入的版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以二的幂,因此13.95将以类似于125650429636838/(2**53)的方式表示 双精度数字具有53位(16位)的精度,常规浮点数具有24位(8位)的精度。用于存储值的 比如说, >>> 125650429603636838/(
a
四舍五入到13.95
该函数的工作方式与我预期的不同。您遇到的是浮点数字,并非所有数字都可以精确表示。命令行只是显示内存中的完整浮点形式
使用浮点表示法时,舍入的版本是相同的数字。由于计算机是二进制的,它们将浮点数存储为整数,然后将其除以二的幂,因此13.95将以类似于125650429636838/(2**53)的方式表示
双精度数字具有53位(16位)的精度,常规浮点数具有24位(8位)的精度。用于存储值的
比如说,
>>> 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
如果仅在小数点后两位(例如,显示货币值),则有两个更好的选择:
您可以修改输出格式:
>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
它完全按照你告诉它的去做,并且工作正常。请阅读更多有关对象的信息,或者尝试使用对象。大多数数字不能用浮点数精确表示。如果你想对数字进行四舍五入,因为这是你的数学公式或算法所要求的,那么你需要使用四舍五入。如果您只是想将显示限制在某个精度,那么甚至不要使用round,只需将其格式化为该字符串即可。(如果要使用其他舍入方法显示,并且有吨,则需要混合使用这两种方法。)
最后,也许最重要的是,如果你想要精确的数学,那么你根本就不想要浮点数。通常的例子是处理金钱和将“美分”存储为整数。Python教程有一个附录,名为。读一下。它解释了正在发生的事情以及Python为什么会做到最好。它甚至有一个与你的例子相匹配的例子。让我引述一点: 您可能会尝试使用
round()
函数将其切回单个
你期望的数字。但这并不重要
区别:
>>> round(0.1, 1)
0.10000000000000001
问题是二进制文件
为“0.1”
已经是最好的二进制文件了
近似于1/10
,因此尝试
再绕一圈也不能让它变得更好:
这已经是最好的了
另一个结果是因为0.1
不完全是1/10
,求和10
0.1
的值可能无法精确生成
1.0
,或者:
>>> sum = 0.0
>>> for i in range(10):
... sum += 0.1
...
>>> sum
0.99999999999999989
解决您的问题的另一种方法是使用该模块。有新的格式规范: 您可以执行以下操作:
"{:.2f}".format(13.949999999999999)
注意1:上面返回一个字符串。为了获得浮点值,只需使用float(…)
:
注意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
请尝试以下代码:
>>> 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),选项二是
有关选项二的更多信息,我建议在上链接
有关选项一的更多信息
参考:为了修复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')
我觉得最简单的方法是使用format()
函数
例如:
a = 13.949999999999999
format(a, '.2f')
13.95
这将生成一个四舍五入到两个小数点的字符串形式的浮点数。要将数字四舍五入到一个分辨率,最好的方法是使用以下方法,可以使用任何分辨率(0.01表示两个小数点或甚至其他步骤):
我使用的方法是字符串切片。这是相对快速和简单的
首先,将浮点值转换为字符串,然后选择希望的长度
float = str(float)[:5]
在上面的一行中,我们将值转换为字符串,然后仅保留字符串的前四位数字或字符(包括)
希望有帮助 TLDR;)
Python 2.7.0和3.1最终解决了输入/输出的舍入问题
正确舍入的数字可以可逆地来回转换:
str->float()->repr()->float()…
或Decimal->float->str->Decimal
存储不再需要十进制类型
(当然,可能需要对四舍五入数字的加减结果进行四舍五入,以消除累积的最后一位错误。显式十进制算法仍然很方便,但通过str()
(即四舍五入到12个有效数字)转换为字符串如果不需要极端精度或连续算术运算的极端次数,则通常足够好。)
无限测试:
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+ :-)
value = 2.34558
precision = 2
width = 4
print(f'result: {value:{width}.{precision}f}')
随机导入
从十进制输入十进制
对于iter中的x(random.random,None):#永远验证舍入是固定的:-)
断言浮点(repr(x))==x#可逆repr()转换。
断言浮点(十进制(repr(x))==x
断言len(repr(舍入(x,10)))=0.1:#隐式舍入到12位有效数字
assert str(x)=repr(round(x,12))#by str()对于小错误来说已经足够好了。
y=1000*x#对于购物来说,十进制类型太多了
assert str(y)=repr(round(y,12-3))#在使用Python 2.7+的超级市场中:-)
文档
见第四段:
在大多数平台上,浮点数和字符串之间的转换现在已正确舍入。这些转换发生在许多不同的地方:浮点数和复数上的str();浮华与复杂
a = 13.949999999999999
format(a, '.2f')
13.95
>>> 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
float = str(float)[:5]
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+ :-)
>>> round(14.22222223, 2)
14.22
print"{:.2f}".format(a)
print"{0:.2f}".format(a)
orig_float = 232569 / 16000.0
short_float = float("{:.2f}".format(orig_float))
>>> f'{a:.2f}'
>>> print(f'Completed in {time.time() - start:.2f}s')
value = 2.34558
precision = 2
width = 4
print(f'result: {value:{width}.{precision}f}')
a = 13.949999999999999
output = float("%0.2f"%a)
print output
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'
d.quantize(Decimal('0.01'))
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)
print(format(14.4499923, '.2f')) // output is 14.45
arred = lambda x,n : x*(10**n)//1/(10**n)
arred(3.141591657,2)
3.14
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')
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)))
x = 1.090675765757
g = float("{:.2f}".format(x))
print(g)
x = 1.090675765757
g = round(x, 2)
print(g)
float_number = 12.234325335563
round(float_number, 2)
12.23
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