python - What happens behind the scene of floor division in Python?
问题描述
The Documentation about the floor division in Python says,
The / (division) and // (floor division) operators yield the quotient of their arguments. The numeric arguments are first converted to a common type. Division of integers yields a float, while floor division of integers results in an integer; the result is that of mathematical division with the ‘floor’ function applied to the result.
I'm focusing on the last line, that says,
the result is that of mathematical division with the ‘floor’ function applied to the result
I get a float
in:
>>> 10//2.0
5.0
But an integer
in:
>>> import math
>>> math.floor(10/2.0)
5
So it's clearly not the math.floor
function that Python floor division is using. I want to know what exact procedure is Python following to compute the floor division of two arguments.
Because when taking the floor division of complex
numbers, Python says,
>>> (2+3j)//(4+5j)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't take floor of complex number.
That means Python takes the division and then applies some sort of floor function. What really is it?
解决方案
比较(都来自该页面):
“地板”功能
如果他们的意思是math.floor
,他们会按照他们的风格来设置它的样式fmod
,即,作为代码并带有math.
前缀、括号和链接。他们的意思只是数学底函数。不是 Python 函数。
深入研究 CPython 是如何实现的,我们先反汇编一下:
>>> import dis
>>> dis.dis('x // y')
1 0 LOAD_NAME 0 (x)
2 LOAD_NAME 1 (y)
4 BINARY_FLOOR_DIVIDE
6 RETURN_VALUE
case TARGET(BINARY_FLOOR_DIVIDE): {
PyObject *divisor = POP();
PyObject *dividend = TOP();
PyObject *quotient = PyNumber_FloorDivide(dividend, divisor);
Py_DECREF(dividend);
Py_DECREF(divisor);
SET_TOP(quotient);
if (quotient == NULL)
goto error;
DISPATCH();
}
PyObject *
PyNumber_FloorDivide(PyObject *v, PyObject *w)
{
return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");
}
抬头看nb_floor_divide
:
+-----------------+------------+-----------------+
| Slot | Type | special methods |
+-----------------+------------+-----------------+
| ... | ... | ... |
| nb_floor_divide | binaryfunc | __floordiv__ |
| ... | ... | ... |
+-----------------+------------+-----------------+
现在int
,floor
两者都有自己的:
>>> int.__floordiv__
<slot wrapper '__floordiv__' of 'int' objects>
>>> float.__floordiv__
<slot wrapper '__floordiv__' of 'float' objects>
static PyNumberMethods float_as_number = {
...
float_floor_div, /* nb_floor_divide */
...
};
抬头看float_floor_div
:
static PyObject *
float_floor_div(PyObject *v, PyObject *w)
{
double vx, wx;
double mod, floordiv;
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float floor division by zero");
return NULL;
}
_float_div_mod(vx, wx, &floordiv, &mod);
return PyFloat_FromDouble(floordiv);
}
抬头看_float_div_mod
:
static void
_float_div_mod(double vx, double wx, double *floordiv, double *mod)
{
...
/* snap quotient to nearest integral value */
if (div) {
*floordiv = floor(div);
if (div - *floordiv > 0.5) {
*floordiv += 1.0;
}
}
...
}
而且我认为floor
它来自 C,因此取决于用于编译 CPython 的任何 C 编译器。
推荐阅读
- java - 使用 Zomato Api 进行改造
- java - 如何在 TestNG 测试套件中最后运行测试
- spring-cloud-config - 从配置服务器读取拆分为多个属性文件的动态配置
- html - CSS 网格未正确呈现
- swift - 如何保存按钮状态
- javascript - 无法将后端 post api 与前端提交按钮链接
- r - 如何在导航栏中添加按钮以显示/隐藏闪亮的侧边栏,如闪亮仪表板
- api - Stack Overflow API 用于使用日期过滤器的流行标签 - 结果没有意义
- firebase - 无法在 Firebase Flutter 应用程序的发布模式下登录谷歌签名问题
- xcode - 测试飞行不断崩溃,但应用程序在开发环境中没问题(React Native)