python中整数除法和浮点数到整数转换之间的区别是什么原因?


52

我最近注意到,int()将浮点数舍入为0,而整数除法将浮点数舍入为底数。

例如:

-7 // 2 = -4
int(-7/2) = -3

我已经阅读了说明以下内容的文档:

类int(x,base = 10)

返回由数字或字符串x构造的整数对象,如果没有给出任何参数,则返回0。如果x是数字,则返回x。int()。对于浮点数,它会截断为零。

和:

楼层划分

四舍五入到最接近的整数的数学除法楼层划分运算符为//。例如,与float true除法返回的2.75相比,表达式11 // 4的计算结果为2。请注意(-11)// 4是-3,因为它是向下向下取整的-2.75。参见PEP 238。

但是对我来说,两个类似的操作(将浮点数除以整数)应该返回不同的结果似乎不合逻辑。

这些功能之间的差异是否有动机?

谢谢。


Answers:


61

一致性。

您需要遵循一些非常基本且看似无关的解释才能理解它。

在学校里,您学习了除法运算。您已经完成了如下计算:

8 ÷ 4 = 2 R 0
7 ÷ 4 = 1 R 3
6 ÷ 4 = 1 R 2
5 ÷ 4 = 1 R 1
4 ÷ 4 = 1 R 0
3 ÷ 4 = 0 R 3
2 ÷ 4 = 0 R 2
1 ÷ 4 = 0 R 1
0 ÷ 4 = 0 R 0
        ^------ This is the result of x // 4
            ^-- This is the result of x % 4 (modulo)

后来,您了解了实数的除法:

8 ÷ 4 = 2.0
7 ÷ 4 = 1.75
6 ÷ 4 = 1.5
5 ÷ 4 = 1.25
4 ÷ 4 = 1.0
3 ÷ 4 = 0.75
2 ÷ 4 = 0.5
1 ÷ 4 = 0.25
0 ÷ 4 = 0.0
        ^--- Note that the number in front of the . is int(x/4)

在此之前,您可能会相信x // 4int(x/4)始终给出相同的结果。这就是您当前对情况的了解。

但是,看看整数除法会发生什么:R后面的数字从3、2、1到0循环,然后重新启动:3、2、1、0。R前面的数字每第4步递减一次。

那么,它将如何进行?

 8 ÷ 4 =  2 R 0
 7 ÷ 4 =  1 R 3
 6 ÷ 4 =  1 R 2
 5 ÷ 4 =  1 R 1
 4 ÷ 4 =  1 R 0
 3 ÷ 4 =  0 R 3
 2 ÷ 4 =  0 R 2
 1 ÷ 4 =  0 R 1
 0 ÷ 4 =  0 R 0
-1 ÷ 4 = -1 R 3
         ^------ We have to decrease now, because we already have 0 four times
              ^-- We have to restart the cycle at 3

同时,实数除法为我们提供:

-1 ÷ 4 = -0.25
          ^----- There is still a 0 in front of the .

这就是为什么-1 // 4给-1但int(-1/4)给0 的原因。

这些功能之间的差异是否有动机?

好吧,它们有不同的用途://是带余数的整数计算int()的一部分,并且为您.提供实数运算前面的部分。

您确定要计算的内容,然后确定要在Python中使用哪个运算符以获得正确的结果。

好问题。继续学习。


11
在实践中,这有一个窍门:如果您有-1种糖果并将其赠送给4个朋友,那么将剩下3种糖果。很好,不是吗?您只需要了解如何拥有-1个糖果即可。
Thomas Weller

1
它确实创建了某种一致性,但据我所知,//在python 3 中添加运算符的动机是为了避免强制使用int(float)。如果不是这种情况,我什么时候应该选择使用来实现int(),当我要实现使用//
IsaacDj

1
好的,那只是一个错误的假设。只要您测试了正确性的假设,这就算不错,在50%的情况下(至少对我而言),这可能会失败。我在答案中添加了一些有关它的词。
Thomas Weller

2
@IsaacDj,您可能想阅读此内容,以了解“楼层划分”运算符背后的故事。
bruno desthuilliers,

1
@EricLippert:我不觉得这很奇怪。我们不能假设有损操作提供与精确操作相同的结果。口语:Math.Floor(3.23) != -Math.Floor(-3.23)出于相同的原因,-((-x)//y)不必相等 x//y
Thomas Weller

4

我要说的是,您的观察表明这两个操作应该在直观上相似,因为在正数上它们的行为相同。但是,如果您查看它们的起源(一个来自数学,另一个来自计算机科学),那么它们的不同行为更有意义。

您可以在其中查看概念:

  • 底数除法又称应用于数学除法的底数函数
  • 类型转换/类型转换

================================================== ================

I)底数除法,即适用于数学除法的底数函数

底函数是数学中一个非常完善的概念。

来自mathworld.wolfram

底函数| _ x_ |,也称为最大整数函数或整数值(Spanier和Oldham 1987),给出小于或等于x的最大整数。发言权功能的名称和符号由KE Iverson创造(Graham等人,1994年)

因此,底数除法就是将底数函数应用于数学除法。行为非常清晰,“数学上精确”。

II)类型转换/类型转换

来自维基百科

在计算机科学中,类型转换,类型转换,类型强制和类型变体是将表达式从一种数据类型更改为另一种数据类型的不同方法。

在大多数编程语言中,通过四舍五入规则应用浮点数到整数的转换形式(因此有一个约定):

  • 向0舍入-向0定向舍入(也称为截断)

根据IEEE 754的舍入规则。


因此,换句话说,python中整数除法和浮点数向int转换之间差异的原因是一种数学上的原因,这是Guido van Rossum的一些想法(我想我不必介绍他了:D)(从博客的Python,文章的历史“为什么Python的整数除法地板”

这打扰了一些人,但是有一个很好的数学理由。整数除法运算(//)及其兄弟运算,取模运算(%)在一起并满足良好的数学关系(所有变量均为整数):

a / b = q,其余为r

这样

b * q + r = a且0 <= r <b

(假设a和b> = 0)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.