Python中的ldexp和frexp如何工作?

2 投票
3 回答
1967 浏览
提问于 2025-04-15 16:36

Python中的frexp和ldexp函数可以把浮点数拆分成两个部分:一个是尾数(mantissa),另一个是指数(exponent)。有人知道这个过程是否直接使用了浮点数的实际结构,还是说需要Python进行比较复杂的对数运算吗?

3 个回答

1

这是一个你可以自己轻松回答的问题:

$ python
>>> import math
>>> help(math.frexp)
Help on built-in function frexp in module math:

注意这里的 built-in。这是在C语言中。

>>> import urllib
>>> help(urllib.urlopen)
Help on function urlopen in module urllib:

这里没有 built-in。这是在Python语言中。

5

Python 2.6中的math.frexp函数其实就是直接调用了底层的C语言库里的frexp。我们可以理解为,这个C语言库直接使用了浮点数的表示方式,而不是去计算这些值(它遵循的是IEEE 754标准)。

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

PyDoc_STRVAR(math_frexp_doc,
"frexp(x)\n"
"\n"
"Return the mantissa and exponent of x, as pair (m, e).\n"
"m is a float and e is an int, such that x = m * 2.**e.\n"
"If x is 0, m and e are both 0.  Else 0.5 <= abs(m) < 1.0.");
1

关于速度,这里有个简单的比较

$ python -m timeit -c 'from math import frexp' 'frexp(1.1)'
100000 loops, best of 3: 3.7 usec per loop

$ python -m timeit -c 'from math import log' 'log(1.1)'
100000 loops, best of 3: 3.7 usec per loop

$ python -m timeit -c 'from math import ldexp' 'ldexp(1.1,2)'
100000 loops, best of 3: 3.5 usec per loop

所以在Python中,frexplogldexp这几个函数在速度上没有太大的区别。不过,这样的比较不一定能告诉你它们的具体实现情况哦!

撰写回答