以下记录和上一篇文章一样,都是根据英文教程的第八章来写的。在Python的C源码中,与内建模块相关的C代码位于Python/bltinmodule.c文件中,该文件里有一个builtin_methods的静态数组,该数组中就定义了内建模块会导入的函数名...

    页面导航: 英文教程的下载地址:

    本篇文章是根据英文教程《Python Tutorial》来写的学习笔记。该英文教程的下载地址如下:

    百度盘地址:http://pan.baidu.com/s/1c0eXSQG

    DropBox地址:点此进入DropBox链接

    Google Drive:点此进入Google Drive链接

    这是学习笔记,不是翻译,因此,内容上会与英文原著有些不同。以下记录和上一篇文章一样,都是根据英文教程的第八章来写的。(文章中的部分链接,可能需要通过代理访问!)

    本篇文章也会涉及到Python的C源代码,这些C源码都是2.7.8版本的。想使用gdb来调试python源代码的话,就需要按照前面"Python基本的操作运算符"文章中所说的,使用configure --with-pydebug命令来重新编译安装python。

概述:

    Python中包含了一些和数学运算相关的函数,如下表所示:

函数名 描述
abs(x) 计算并返回参数x的绝对值,即x与零点之间的距离值。
ceil(x) 计算出x的上限,即函数会返回不小于x的最小整数值。
cmp(x, y) 比较x与y的值,如果x小于y则返回-1,如果x等于y返回0,如果x大于y则返回1 。
exp(x) 计算出 ex 即e的x次方,e是数学中最重要的常数之一,其概念可以参考 e_数学常数 该链接对应的维基百科文章。
fabs(x) 也是计算出参数x的绝对值,与上面abs函数的区别在于:fabs函数无法计算复数的绝对值,另外,fabs返回的结果始终是个浮点数,
而abs函数会根据参数来决定返回的结果类型,比如当abs函数的参数是个整数时,abs函数就会返回整数类型的结果。在下面会对这两个
函数进行举例说明。
floor(x) 计算出x的下限,即函数会返回不大于x的最大整数值。
log(x) 计算并返回参数x的自然对数,参数x必须大于0,当x小于等于0时,会产生domain error的域错误。
有关自然对数的概念,可以参考 自然对数 该链接对应的维基百科文章。
log10(x) 计算出以10为底的x的对数,参数x同样必须大于0,当x小于等于0时,会产生domain error的域错误。
有关对数的概念,可以参考 对数 该链接对应的维基百科文章。
max(x1, x2,...) 从max函数的参数中找到最大值,并返回该值。
min(x1, x2,...) 从min函数的参数中找到最小值,并返回该值。
modf(x) 返回参数x的小数与整数部分,这两部分会以元组的形式进行返回,下面会进行举例说明。
pow(x, y) 计算并返回x的y次方的值。
round(x [,n]) 对参数x进行四舍五入,第二个参数n是可选的,表示舍入到小数点后的第几位。
sqrt(x) 计算参数x的平方根,参数x的值必须大于等于0,否则会产生domain error的域错误。

内建模块里的函数:

    上表的函数中:abs,cmp,max,min及round函数,都是 __builtin__ 即内建模块里的Python函数,在Python的C源码中,与内建模块相关的C代码位于Python/bltinmodule.c文件中,该文件里有一个builtin_methods的静态数组,该数组中就定义了内建模块会导入的函数名:

static PyMethodDef builtin_methods[] = {
    {"__import__",      (PyCFunction)builtin___import__, METH_VARARGS | METH_KEYWORDS, import_doc},
    {"abs",             builtin_abs,        METH_O, abs_doc},
    {"all",             builtin_all,        METH_O, all_doc},
    {"any",             builtin_any,        METH_O, any_doc},
    {"apply",           builtin_apply,      METH_VARARGS, apply_doc},
    {"bin",             builtin_bin,        METH_O, bin_doc},
    {"callable",        builtin_callable,   METH_O, callable_doc},
    {"chr",             builtin_chr,        METH_VARARGS, chr_doc},
    {"cmp",             builtin_cmp,        METH_VARARGS, cmp_doc},
    {"coerce",          builtin_coerce,     METH_VARARGS, coerce_doc},
    {"compile",         (PyCFunction)builtin_compile,    METH_VARARGS | METH_KEYWORDS, compile_doc},
    {"delattr",         builtin_delattr,    METH_VARARGS, delattr_doc},
    {"dir",             builtin_dir,        METH_VARARGS, dir_doc},
    {"divmod",          builtin_divmod,     METH_VARARGS, divmod_doc},
    {"eval",            builtin_eval,       METH_VARARGS, eval_doc},
    {"execfile",        builtin_execfile,   METH_VARARGS, execfile_doc},
    {"filter",          builtin_filter,     METH_VARARGS, filter_doc},
    {"format",          builtin_format,     METH_VARARGS, format_doc},
    {"getattr",         builtin_getattr,    METH_VARARGS, getattr_doc},
    {"globals",         (PyCFunction)builtin_globals,    METH_NOARGS, globals_doc},
    {"hasattr",         builtin_hasattr,    METH_VARARGS, hasattr_doc},
    {"hash",            builtin_hash,       METH_O, hash_doc},
    {"hex",             builtin_hex,        METH_O, hex_doc},
    {"id",              builtin_id,         METH_O, id_doc},
    {"input",           builtin_input,      METH_VARARGS, input_doc},
    {"intern",          builtin_intern,     METH_VARARGS, intern_doc},
    {"isinstance",  builtin_isinstance, METH_VARARGS, isinstance_doc},
    {"issubclass",  builtin_issubclass, METH_VARARGS, issubclass_doc},
    {"iter",            builtin_iter,       METH_VARARGS, iter_doc},
    {"len",             builtin_len,        METH_O, len_doc},
    {"locals",          (PyCFunction)builtin_locals,     METH_NOARGS, locals_doc},
    {"map",             builtin_map,        METH_VARARGS, map_doc},
    {"max",             (PyCFunction)builtin_max,        METH_VARARGS | METH_KEYWORDS, max_doc},
    {"min",             (PyCFunction)builtin_min,        METH_VARARGS | METH_KEYWORDS, min_doc},
    {"next",            builtin_next,       METH_VARARGS, next_doc},
    {"oct",             builtin_oct,        METH_O, oct_doc},
    {"open",            (PyCFunction)builtin_open,       METH_VARARGS | METH_KEYWORDS, open_doc},
    {"ord",             builtin_ord,        METH_O, ord_doc},
    {"pow",             builtin_pow,        METH_VARARGS, pow_doc},
    {"print",           (PyCFunction)builtin_print,      METH_VARARGS | METH_KEYWORDS, print_doc},
    {"range",           builtin_range,      METH_VARARGS, range_doc},
    {"raw_input",       builtin_raw_input,  METH_VARARGS, raw_input_doc},
    {"reduce",          builtin_reduce,     METH_VARARGS, reduce_doc},
    {"reload",          builtin_reload,     METH_O, reload_doc},
    {"repr",            builtin_repr,       METH_O, repr_doc},
    {"round",           (PyCFunction)builtin_round,      METH_VARARGS | METH_KEYWORDS, round_doc},
    {"setattr",         builtin_setattr,    METH_VARARGS, setattr_doc},
    {"sorted",          (PyCFunction)builtin_sorted,     METH_VARARGS | METH_KEYWORDS, sorted_doc},
    {"sum",             builtin_sum,        METH_VARARGS, sum_doc},
#ifdef Py_USING_UNICODE
    {"unichr",          builtin_unichr,     METH_VARARGS, unichr_doc},
#endif
    {"vars",            builtin_vars,       METH_VARARGS, vars_doc},
    {"zip",         builtin_zip,        METH_VARARGS, zip_doc},
    {NULL,              NULL},
};


    由于内建模块在Python运行时,默认就已经被导入了的。因此,定义在上面数组中的Python函数都可以直接使用,如下例所示:

[email protected]:~$ python
Python 2.7.8 (default, Feb 20 2015, 12:54:46) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> abs(-3)
3
>>> abs(-3.5)
3.5
>>> abs(3+4j)
5.0
>>> cmp(4,3)
1
>>> max(1,3,5,8,100,200)
200
>>> min(1,3,5,8,100,200)
1
>>> round(3.563)
4.0
>>> round(3.563, 0)
4.0
>>> round(3.563, 1)
3.6
>>> round(3.555, 2)
3.56
>>> round(3.565, 2)
3.56
>>> round(3.563, -1)
0.0
>>> round(3.563, -2)
0.0
>>> quit()
[email protected]:~$ 


    从上面的例子中,可以看到,abs函数还可以计算出复数的绝对值,如上面的 abs(3+4j) 的值为5.0 ,该结果其实就是 32 + 42 的值再开平方根,即以3和4为直角边的直角三角形的斜边值。

    当round函数没有提供第二个参数的时候,该函数就只计算出整数部分的四舍五入的值,如上面的 round(3.563) ,结果就是4.0 。

    当round函数的第二个参数为0时,它也只会计算整数部分,如上面的 round(3.563, 0) ,结果也是4.0 。

    当round函数的第二个参数大于0时,它会对小数部分进行舍入操作,如上面的 round(3.563, 1) 会对小数点后的第一位进行舍入操作,结果就是3.6 ,round(3.555, 2) 会对小数点后的第二位进行舍入操作,结果就是3.56 。

    但是,由于浮点数在计算机内部保存时,本身就会存在一个精度问题,因此,这种舍入操作有时候就不会得到预期的值,如上面的 round(3.565, 2) ,得到的结果 3.56 就不是预期的值。

    当round函数的第二个参数小于0时,得到的结果就会是0,如上面的 round(3.563, -1) round(3.563, -2)

math模块里的函数:

    前面数学运算表格中介绍的ceil,exp,fabs,floor,log,log10,modf,pow及sqrt函数都是math模块中定义的函数,在Python的C源码里,与math模块相关的C代码位于Modules/mathmodule.c文件里,该文件中也有一个静态数组:

static PyMethodDef math_methods[] = {
    {"acos",            math_acos,      METH_O,         math_acos_doc},
    {"acosh",           math_acosh,     METH_O,         math_acosh_doc},
    {"asin",            math_asin,      METH_O,         math_asin_doc},
    {"asinh",           math_asinh,     METH_O,         math_asinh_doc},
    {"atan",            math_atan,      METH_O,         math_atan_doc},
    {"atan2",           math_atan2,     METH_VARARGS,   math_atan2_doc},
    {"atanh",           math_atanh,     METH_O,         math_atanh_doc},
    {"ceil",            math_ceil,      METH_O,         math_ceil_doc},
    {"copysign",        math_copysign,  METH_VARARGS,   math_copysign_doc},
    {"cos",             math_cos,       METH_O,         math_cos_doc},
    {"cosh",            math_cosh,      METH_O,         math_cosh_doc},
    {"degrees",         math_degrees,   METH_O,         math_degrees_doc},
    {"erf",             math_erf,       METH_O,         math_erf_doc},
    {"erfc",            math_erfc,      METH_O,         math_erfc_doc},
    {"exp",             math_exp,       METH_O,         math_exp_doc},
    {"expm1",           math_expm1,     METH_O,         math_expm1_doc},
    {"fabs",            math_fabs,      METH_O,         math_fabs_doc},
    {"factorial",       math_factorial, METH_O,         math_factorial_doc},
    {"floor",           math_floor,     METH_O,         math_floor_doc},
    {"fmod",            math_fmod,      METH_VARARGS,   math_fmod_doc},
    {"frexp",           math_frexp,     METH_O,         math_frexp_doc},
    {"fsum",            math_fsum,      METH_O,         math_fsum_doc},
    {"gamma",           math_gamma,     METH_O,         math_gamma_doc},
    {"hypot",           math_hypot,     METH_VARARGS,   math_hypot_doc},
    {"isinf",           math_isinf,     METH_O,         math_isinf_doc},
    {"isnan",           math_isnan,     METH_O,         math_isnan_doc},
    {"ldexp",           math_ldexp,     METH_VARARGS,   math_ldexp_doc},
    {"lgamma",          math_lgamma,    METH_O,         math_lgamma_doc},
    {"log",             math_log,       METH_VARARGS,   math_log_doc},
    {"log1p",           math_log1p,     METH_O,         math_log1p_doc},
    {"log10",           math_log10,     METH_O,         math_log10_doc},
    {"modf",            math_modf,      METH_O,         math_modf_doc},
    {"pow",             math_pow,       METH_VARARGS,   math_pow_doc},
    {"radians",         math_radians,   METH_O,         math_radians_doc},
    {"sin",             math_sin,       METH_O,         math_sin_doc},
    {"sinh",            math_sinh,      METH_O,         math_sinh_doc},
    {"sqrt",            math_sqrt,      METH_O,         math_sqrt_doc},
    {"tan",             math_tan,       METH_O,         math_tan_doc},
    {"tanh",            math_tanh,      METH_O,         math_tanh_doc},
    {"trunc",           math_trunc,     METH_O,         math_trunc_doc},
    {NULL,              NULL}           /* sentinel */
};


    上面math_methods数组中定义的函数,都是math模块里的函数,在使用这些函数时,需要先导入math模块,如下例所示:

[email protected]:~$ python
Python 2.7.8 (default, Feb 20 2015, 12:54:46) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> math.ceil(3.3)
4.0
>>> math.floor(3.3)
3.0
>>> math.exp(1)
2.718281828459045
>>> math.fabs(3)
3.0
>>> math.fabs(-3)
3.0
>>> math.log(2)
0.6931471805599453
>>> math.log10(2)
0.3010299956639812
>>> math.modf(3.1415)
(0.14150000000000018, 3.0)
>>> math.modf(-3.1415)
(-0.14150000000000018, -3.0)
>>> math.pow(2, 3)
8.0
>>> pow(2, 3)
8
>>> 2**3
8
>>> sqrt(25)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sqrt' is not defined
>>> math.sqrt(25)
5.0
>>> quit()
[email protected]:~$ 


    在使用这些math模块的函数之前,需要先执行 import math 语句,来将math模块导入进来,在调用函数时,还需要指明模块名,如math.sqrt(25),如果只用sqrt(25)语句的话,就会报如上所示的 name 'sqrt' is not defined 的错误。

    上面的ceil函数会计算出不小于参数的最小整数值,如 math.ceil(3.3) 的结果就是4.0 。

    floor函数会计算出不大于参数的最大整数值,如 math.floor(3.3) 的结果就是3.0 。

    exp函数可以计算常数e的指数,当将exp的参数设为1时,得到的就会是e1 即e的1次方,也就是常数e的值。因此,从上面 math.exp(1) 执行的结果可以看到,e的值大约是2.718281828459045 。

    modf函数会将浮点数的小数与整数部分以tuple元组的形式进行返回,如上面的 math.modf(3.1415) 的结果就是 (0.14150000000000018, 3.0) ,元组里的第一个元素为小数部分,第二个元素为整数部分,小数部分存在一个精度误差在里面。另外,元组里的小数部分与整数部分具有和modf函数的参数相同的符号位,即当参数是正数时,这两部分就都是正数,当参数为负数时,则这两部分就都是负数,如上面的 math.modf(-3.1415) 的返回结果就是 (-0.14150000000000018, -3.0)。

    pow函数用于计算参数的指数值,例如上面的 pow(2, 3) 相当于2**3,即2的3次方,这里需要注意的地方是:在内建模块里也有一个同名的pow函数,内建模块里的pow函数的返回结果的类型是根据参数的类型来决定的:当参数都是整数时,返回的结果就是整数值,当参数为浮点数时,返回的结果就是浮点数,如上面的 pow(2, 3) 返回的就是整数8,而math.pow函数返回的始终是浮点数,如 math.pow(2, 3) 返回的就是浮点数8.0

    sqrt函数则用于计算平方根,如上面的 math.sqrt(25) 的结果就是5.0 。

    下面再来看下fabs与abs函数的区别:

[email protected]:~$ python
Python 2.7.8 (default, Feb 20 2015, 12:54:46) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> type(abs(-2))
<type 'int'>
>>> type(abs(-2.0))
<type 'float'>
>>> type(abs(3+4j))
<type 'float'>
>>> import math
>>> type(math.fabs(-2))
<type 'float'>
>>> type(math.fabs(-2.0))
<type 'float'>
>>> type(math.fabs(3+4j))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float
>>> quit()
[email protected]:~$ 


    可以看到,abs函数会根据参数的类型来决定返回结果的类型。

    当参数为整数时,abs函数返回的结果就会是整数值,如上面的abs(-2)返回的就是int类型的整数结果。

    当参数为浮点数或复数时,abs函数返回的结果就会是个浮点数,如上面的abs(-2.0)与abs(3+4j)返回的就是float类型的浮点数。

    math.fabs函数则无论参数是整数还是浮点数,返回的结果都会是float类型的浮点数。此外,math.fabs函数不能计算复数的绝对值。

    通过分析math模块对应的C源码,即Modules/mathmodule.c文件可知:math模块里的这些数学运算函数,最终会调用C语言的数学库即libm.so里的同名函数,去执行具体的运算操作。在Linux系统下,可以通过man命令来查看libm.so库里定义的这些函数的相关帮助信息:

[email protected]:~$ man ceil
CEIL(3)                    Linux Programmer's Manual                   CEIL(3)

NAME
       ceil, ceilf, ceill - ceiling function: smallest integral value not less
       than argument

SYNOPSIS
       #include <math.h>

       double ceil(double x);
       float ceilf(float x);
       long double ceill(long double x);
....................................................
[email protected]com:~$ man floor
FLOOR(3)                   Linux Programmer's Manual                  FLOOR(3)

NAME
       floor,  floorf,  floorl - largest integral value not greater than argu‐
       ment

SYNOPSIS
       #include <math.h>

       double floor(double x);
       float floorf(float x);
       long double floorl(long double x);
....................................................
[email protected]:~$ man exp
EXP(3)                     Linux Programmer's Manual                    EXP(3)

NAME
       exp, expf, expl - base-e exponential function

SYNOPSIS
       #include <math.h>

       double exp(double x);
       float expf(float x);
       long double expl(long double x);

       Link with -lm.
....................................................
[email protected]:~$ man fabs
FABS(3)                    Linux Programmer's Manual                   FABS(3)

NAME
       fabs, fabsf, fabsl - absolute value of floating-point number

SYNOPSIS
       #include <math.h>

       double fabs(double x);
       float fabsf(float x);
       long double fabsl(long double x);

       Link with -lm.
....................................................
[email protected]:~$ man log
LOG(3)                     Linux Programmer's Manual                    LOG(3)

NAME
       log, logf, logl - natural logarithmic function

SYNOPSIS
       #include <math.h>

       double log(double x);
       float logf(float x);
       long double logl(long double x);
....................................................
[email protected]:~$ man log10
LOG10(3)                   Linux Programmer's Manual                  LOG10(3)

NAME
       log10, log10f, log10l -  base-10 logarithmic function

SYNOPSIS
       #include <math.h>

       double log10(double x);
       float log10f(float x);
       long double log10l(long double x);
....................................................
[email protected]:~$ man modf
MODF(3)                    Linux Programmer's Manual                   MODF(3)

NAME
       modf, modff, modfl - extract signed integral and fractional values from
       floating-point number

SYNOPSIS
       #include <math.h>

       double modf(double x, double *iptr);
       float modff(float x, float *iptr);
       long double modfl(long double x, long double *iptr);
....................................................
[email protected]:~$ man pow
POW(3)                     Linux Programmer's Manual                    POW(3)

NAME
       pow, powf, powl - power functions

SYNOPSIS
       #include <math.h>

       double pow(double x, double y);
       float powf(float x, float y);
       long double powl(long double x, long double y);
....................................................
[email protected]:~$ man sqrt
SQRT(3)                    Linux Programmer's Manual                   SQRT(3)

NAME
       sqrt, sqrtf, sqrtl - square root function

SYNOPSIS
       #include <math.h>

       double sqrt(double x);
       float sqrtf(float x);
       long double sqrtl(long double x);
....................................................
[email protected]:~$ 


    因此,只要理解了C库里这些底层函数的作用,就可以充分理解Python中math模块里的这些同名函数的作用了。从上面的帮助信息中还可以看到,这些math里的数学函数,返回的结果都是double类型的浮点数。因此,前面介绍的fabs之类的math模块里的函数的返回结果,始终是浮点数。

    限于篇幅,本章先到这里,下一篇将介绍和随机数相关的python函数。

    OK,休息,休息一下 o(∩_∩)o~~

    业精于勤而荒于嬉,行成于思而毁于随

——  韩愈
 
上下篇

下一篇: Python随机数函数

上一篇: Python的数字类型及相关的类型转换函数

相关文章

Python元组类型及相关函数

Python定义和使用模块

Python基本的I/O操作 (四)

Python的安装与使用

Python列表相关的脚本函数

Python的time模块