Python的楼层分割幕后发生了什么?

问题描述

关于Python的楼层划分的Documentation说,

/(除法)和//(底数除法)运算符产生其参数的商。首先将数字参数转换为通用类型。整数除法产生一个浮点数,而整数除法产生一个整数。结果是对数学结果进行了除法,并将“ floor”函数应用于结果。

我专注于最后一行,

结果是对结果应用了“ floor”功能的数学除法运算

我收到一个float

>>> 10//2.0
5.0

但其中有integer

>>> import math
>>> math.floor(10/2.0)
5

因此,显然不是Python地板部门使用的math.floor函数。我想知道Python用于计算两个参数的底数划分的确切过程是什么。

Python说,因为当对complex个数字进行下限分割时,

>>> (2+3j)//(4+5j)
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
TypeError: can't take floor of complex number.

这意味着Python进行除法,然后应用某种场函数。到底是什么?

解决方法

比较(均来自该页面):

“楼层”功能

函数math.fmod()

如果它们的意思是math.floor,则它们的样式应与样式为fmod的样式相同,即,作为代码,并带有math.前缀,括号和链接。他们所做的意味着只有数学上的floor function。不是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

查找BINARY_FLOOR_DIVIDE

        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();
        }

查找PyNumber_FloorDivide

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__    |
| ...             | ...        | ...             |
+-----------------+------------+-----------------+

现在intfloor都有自己的地方:

>>> int.__floordiv__
<slot wrapper '__floordiv__' of 'int' objects>
>>> float.__floordiv__
<slot wrapper '__floordiv__' of 'float' objects>

查找the float one的功能:

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语言编译器。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...