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

Isa*_*cDj 56 python integer-division python-3.x

我最近注意到将int()浮点数舍入到 0,而整数除法将浮点数舍入到它的下限。

例如:

-7 // 2 = -4
int(-7/2) = -3
Run Code Online (Sandbox Code Playgroud)

我已阅读指定的文档:

类 int(x, base=10)

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

和:

楼层划分

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

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

功能之间的差异是否有任何动机?

谢谢你。

Tho*_*ler 66

一致性。

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

在学校,你已经学会了除法和余数。你已经完成了这样的计算:

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)
Run Code Online (Sandbox Code Playgroud)

后来,你学习了实数的除法:

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)
Run Code Online (Sandbox Code Playgroud)

在此之前,您可能会相信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
Run Code Online (Sandbox Code Playgroud)

同时,实数除法给我们:

-1 ÷ 4 = -0.25
          ^----- There is still a 0 in front of the .
Run Code Online (Sandbox Code Playgroud)

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

功能之间的差异是否有任何动机?

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

您决定要计算什么,然后决定在 Python 中使用哪个运算符来获得正确的结果。

好问题。继续学习。

  • 在实践中,这允许一个技巧:如果你有 -1 颗糖果,并且你把它送给 4 个朋友,那么就会剩下 3 颗糖果。太棒了,不是吗?你只需要了解如何拥有-1糖果。 (14认同)
  • @IsaacDj,您可能想[阅读本文](https://www.python.org/dev/peps/pep-0238/)了解“地板除法”运算符背后的故事。 (2认同)
  • @EricLippert:我不认为这很奇怪。我们不能假设有损操作提供与精确操作相同的结果。用代码来说: `Math.Floor(3.23) != -Math.Floor(-3.23)` 出于同样的原因,`-((-x)//y)` 不需要等于 `x//y`。 (2认同)

rus*_*ro1 7

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

你可以看看后面的概念:

  • 地板除法又名地板函数应用于数学除法
  • 类型转换/类型转换

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

I)Floor Division 也就是应用于数学除法的 floor 函数

楼层函数是数学中一个非常成熟的概念。

来自mathworld.wolfram

底函数 |_ x_ |,也称为最大整数函数或整数值(Spanier 和 Oldham 1987),给出小于或等于 x 的最大整数。楼层函数的名称和符号由 KE Iverson 创造(Graham et al. 1994)

所以楼层除法无非是应用于数学除法的楼层函数。行为非常明确,“数学上精确”。

II) 类型转换/类型转换

来自维基百科

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

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

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

根据IEEE 754 的舍入规则。


所以,换句话说,python 中整数除法和浮点到整数转换之间差异的原因是数学上的,这里是 Guido van Rossum 的一些想法(我想我不必介绍他:D)(来自博客 Python 的历史,文章“为什么 Python 的整数除法层”

这让一些人感到不安,但有一个很好的数学原因。整数除法运算 (//) 和它的兄弟,模运算 (%),一起满足一个很好的数学关系(所有变量都是整数):

a/b = q 余数为 r

以至于

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

(假设 a 和 b >= 0)。