8

奇怪的是,Python 数学模块中的每个函数似乎都可以很好地处理 Decimal 对象。例如:freexp、exp、cos。

当我输入 时print(math.frexp(decimal.Decimal('2341.12412'))),Python 会打印出正确的答案,即(0.57156... , 12), 并且不会抛出任何异常。

我假设数学模块将用低级 C 编写,尽可能依赖硬件数学运算来提高效率。那么......为什么它适用于 Decimal 对象?

他们是否对数学函数进行了类型检查,如果参数是十进制,则切换到不同的实现?我没有看到文档中提到的类似内容。也可能是 Decimal 自动转换为浮点数,但这也没有任何意义。

是的,我很困惑。

4

1 回答 1

7

好吧,看看math module.c我得到了这个:

static PyObject *
math_frexp(PyObject *self, PyObject *arg)
{
    int i;
    double x = PyFloat_AsDouble(arg);
    if (x == -1.0 && PyErr_Occurred())
        return NULL;
    /* deal with special cases directly, to sidestep platform
       differences */
    if (Py_IS_NAN(x) || Py_IS_INFINITY(x) || !x) {
        i = 0;
    }
    else {
        PyFPE_START_PROTECT("in math_frexp", return 0);
        x = frexp(x, &i);
        PyFPE_END_PROTECT(x);
    }
    return Py_BuildValue("(di)", x, i);
}

查看代码,它确实使用float( PyFloat_AsDouble)

同样的事情exp

static PyObject *
math_factorial(PyObject *self, PyObject *arg)
{
    long x;
    PyObject *result, *odd_part, *two_valuation;

    if (PyFloat_Check(arg)) {
        PyObject *lx;
        double dx = PyFloat_AS_DOUBLE((PyFloatObject *)arg);
        if (!(Py_IS_FINITE(dx) && dx == floor(dx))) {
            PyErr_SetString(PyExc_ValueError,
                            "factorial() only accepts integral values");
            return NULL;
        }
        lx = PyLong_FromDouble(dx);
        if (lx == NULL)
            return NULL;
        x = PyLong_AsLong(lx);
        Py_DECREF(lx);
.........................................................
于 2013-04-06T03:44:08.290 回答