Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么是数学。地板(x/y)!=Python中两个可等分浮点的x//y?_Python_Division_Integer Division - Fatal编程技术网

为什么是数学。地板(x/y)!=Python中两个可等分浮点的x//y?

为什么是数学。地板(x/y)!=Python中两个可等分浮点的x//y?,python,division,integer-division,Python,Division,Integer Division,我一直在阅读Python中的除法和整数除法,以及Python2和Python3中除法的区别。在大多数情况下,这一切都是有道理的。Python 2仅当两个值都是整数时才使用整数除法。Python3总是执行真正的除法。Python 2.2+引入了整数除法的/运算符 其他程序员提供了一些很好且简洁的示例,例如: >>> 1.0 // 2.0 # floors result, returns float 0.0 >>> -1 // 2 # n

我一直在阅读Python中的除法和整数除法,以及Python2和Python3中除法的区别。在大多数情况下,这一切都是有道理的。Python 2仅当两个值都是整数时才使用整数除法。Python3总是执行真正的除法。Python 2.2+引入了整数除法的
/
运算符

其他程序员提供了一些很好且简洁的示例,例如:

>>> 1.0 // 2.0      # floors result, returns float
0.0
>>> -1 // 2         # negatives are still floored
-1
如何实现
/
?为什么会发生以下情况:

>>> import math
>>> x = 0.5 
>>> y = 0.1
>>> x / y
5.0
>>> math.floor(x/y)
5.0
>>> x // y
4.0
不应该
x//y=math.floor(x/y)
?这些结果是在python2.7上产生的,但由于x和y都是浮体,因此在python3+上的结果应该是相同的。如果在
x/y
实际上是
4.9999999999999999
math.floor(4.9999999999999)==4.0
的地方存在浮点错误,这不会反映在
x/y
中吗

但是,以下类似情况不受影响:

>>> (.5*10) // (.1*10)
5.0
>>> .1 // .1
1.0
那是因为

>>> .1
0.10000000000000001
.1
不能用二进制精确表示

你也可以看到

>>> .5 / 0.10000000000000001
5.0

问题是Python会将输出四舍五入为整数。由于
0.1
不能用二进制精确表示,因此结果类似于
4.999999999999722444243844000
。当不使用格式时,这自然会变成
5.0

其他答案我都不满意。当然,
.1
没有有限的二进制扩展,所以我们的直觉是表示错误是罪魁祸首。但这一直觉本身并不能真正解释为什么
math.floor(.5/.1)
产生
5.0
,而
.5/.1
产生
4.0

有趣的是
a//b
实际上是
floor((a-(a%b))/b)
,而不是简单的
floor(a/b)

.5/.1正好是5.0 首先,请注意,
.5/.1
的结果在Python中正好是
5.0
。即使不能准确表示
.1
,情况也是如此。以这段代码为例:

from decimal import Decimal

num = Decimal(.5)
den = Decimal(.1)
res = Decimal(.5/.1)

print('num: ', num)
print('den: ', den)
print('res: ', res)
以及相应的输出:

num:  0.5
den:  0.1000000000000000055511151231257827021181583404541015625
res:  5
这表明
.5
可以用有限的二进制扩展来表示,但
.1
不能。但它也表明,尽管如此,
.5/.1
的结果恰恰是
5.0
。这是因为浮点除法会导致精度损失,并且在此过程中,
den
.1
的差异量会丢失

这就是为什么
math.floor(.5/.1)
的工作方式与您预期的一样:因为
.5/.1
5.0
,所以编写
math.floor(.5/.1)
与编写
math.floor(5.0)
是一样的

那么为什么
.5/.1
不产生5呢? 人们可能认为
.5/.1
楼层(.5/.1)
的简写,但事实并非如此。事实证明,语义不同。尽管:

楼层划分将在所有区域实施 类型,并将具有

    a // b == floor(a/b)
事实证明,
.5//.1
的语义实际上相当于:

floor((.5 - mod(.5, .1)) / .1)
其中,
mod
.5/.1
的浮点余数向零舍入。这一点可以通过阅读文章来明确

这就是为什么
.1
不能用二进制扩展精确表示的原因。
.5/.1
的浮点余数为零:

>>> .5 % .1
0.09999999999999998
事实并非如此,这是有道理的。由于
.1
的二进制扩展比实际的十进制
.1
稍大,因此最大的整数
alpha
,因此
alpha*.1

恐怕这不对。5/.1正好是5.0。请参见:(.5/.1).as_integer_ratio(),其结果为(5,1)

是的,
5
可以表示为
5/1
,这是正确的。但是为了查看Python由于不精确的表示而给出的实际结果的分数,请继续

第一,进口:

from decimal import *
from fractions import Fraction
易于使用的变量:

// as_integer_ratio() returns a tuple
xa = Decimal((.5).as_integer_ratio()[0])
xb = Decimal((.5).as_integer_ratio()[1])
ya = Decimal((.1).as_integer_ratio()[0])
yb = Decimal((.1).as_integer_ratio()[1])
产生以下值:

xa = 1
xb = 2
ya = 3602879701896397
yb = 36028797018963968
当然,
1/2==5
3602879701896397/36028797018963968==0.100000000000000551151231

那么当我们分开时会发生什么呢

>>> print (xa/xb)/(ya/yb)
4.999999999999999722444243845
但是当我们想要整数比率的时候

>>> print float((xa/xb)/(ya/yb)).as_integer_ratio()
(5, 1)
如前所述,
5
当然是
5/1
。这就是
Fraction
的作用:

>>> print Fraction((xa/xb)/(ya/yb))
999999999999999944488848769/200000000000000000000000000
并确认这确实是
4.999999999999722444243845


为什么不直接做
分数(.5/.1)
分数(十进制(.5)/十进制(.1))


后者将为我们提供相同的
5/1
结果。前者将为我们提供
12499999999999930611060961/25000000000000000000000000
。这将导致
4.999999999999972444243844
,类似但不相同的结果。

@J.Money:try
(0.1)。as_integer_ratio()
格式(0.1,'1.30f')
这不应该是公认的答案。我猜从技术上来说,它回答了OP的问题,但没有解释。请使用以下链接更新您的答案,使其更加完整:,@searchengine27
。1不能用二进制表示,这还不够解释吗?(另外,其他答案给出了不同层次的详细信息,user5248483发布了一个指向Python3浮动教程的链接,该教程在解释所有细节方面做得非常好)甚至没有接近。浮点数的公式在哪里?对事物实际如何表现的解释?说“那不行”并不等于说“这就是它的工作原理”。参考IEEE 754可能是一个开始,但你甚至没有努力做到这一点。说别人给出了正确的答案,并不能使你的答案正确。这使他们的答案正确,a
>>> print float((xa/xb)/(ya/yb)).as_integer_ratio()
(5, 1)
>>> print Fraction((xa/xb)/(ya/yb))
999999999999999944488848769/200000000000000000000000000