scipy.special.binom和scipy.misc.comb有什么区别?

时间:2014-02-03 19:21:12

标签: python scipy

scipy.special.binom和scipy.misc.comb有什么区别?

在ipython中我可以看到它们返回不同的类型,但也有不同的准确性。

scipy.special.binom(4,3)
4.0

scipy.misc.comb(4,3)
array(4.000000000000001)

然而,他们究竟采取了不同的做法?


查看https://github.com/scipy/scipy/blob/master/scipy/special/generate_ufuncs.py,scipy.special.binom说

binom -- binom: dd->d                                      -- orthogonal_eval.pxd

scipy.misc.comb调用scipy.special.gammaln,其行在generate_ufuncs.py中表示

gammaln -- lgam: d->d, clngamma_wrap: D->D                 -- cephes.h, specfun_wrappers.h

1 个答案:

答案 0 :(得分:11)

每当遇到一些你不知道某些代码正在做什么的情况时,简单地在某个解释器中导入父模块并检查代码,文档字符串等的执行情况并不容易,那么你有几个选择。

让我描述两个选项,但这次没有发挥作用,但这是一个很好的方式来开始这样的问题在未来(这样你可以包括这些尝试的输出,以证明人们你在发布之前尝试了一些东西,看起来很想知道这些东西是什么):

您可以使用dis模块将Python代码反汇编为已执行的操作码,如下所示:

python -c "import dis; from scipy import misc; print dis.dis('misc.comb(4,3)')"
python -c "import dis; from scipy import special; print dis.dis('special.binom(4,3)')"

如果使用* nix操作系统,您也可以(几乎总是)使用strace启动某些内容并检查所进行的系统调用。在这种情况下,您可以查看

的输出
strace -qc python -c "from scipy import special; special.binom(4,3)"

strace -qc python -c "from scipy import misc; special.comb(4,3)"

-qc选项使得输出不那么繁琐并聚合在不同系统调用中花费的时间,这可以更容易作为第一次启动阅读。如果省略-qc部分,你'我将获得所有系统调用的大屏幕转储...你想要在Emacs中打开并搜索,或者通过管道传输到系统工具进行搜索。

在这种情况下,strace没有太多帮助,并且有很多与模块导入相关的嘈杂系统调用。

这次对我有用的是cProfile

python -c "import cProfile; cProfile.run('from scipy import special; special.binom(4,3)')"

在这种情况下,我能够看到第一次执行归结为对scipy.special.orthogonal_eval的系统调用,并且谷歌搜索此模块显示我们正在谈论一个共享库,构建为文件{{1}我找到了这个nice page with the source code

你可以在那里看到orthogonal_eval.so的完整函数定义,其中包括小值公式中涉及的阶乘的标准计算,以及与其他特殊函数的一些近似(我看到一些调用“Gamma”) ,“beta”和“lbeta”在一个名为binom的文件中定义。

看起来非常标准 - 如果我需要,我可以去挖掘那个cephes.h文件和谷歌更多,并且可能在所有这些的底部找到一个长期存在的特殊功能的C库。 / p>

同时,.h首先考虑regular documentationview the source是可用的(而对我来说,它不适用于misc.comb)。

docstring说有一个可能的第三个参数binom,如果想要返回exact,可以将其设置为0以外的值。在这种情况下,会返回float,但如果您愿意,可以投放到long

这解释了精确度问题。您可以在int中读取如果orthogonal_eval相对较小,并且答案将给出整数(整数参数),则使用具有较少舍入误差的内容。而k只会在您comb(或其他任何exact=1)的情况下执行此操作。

对于exact != 0正在执行的代码,我们可以{{3}}从SciPy文档页面链接。

这个函数也使用了来自comb的一些辅助函数调用,但是Python层和C层中调用的函数之间的混合是不同的,并且近似部分的实现略有不同,好。

我不确定您需要什么级别的特异性,但我想说,对于大多数用途,此详细程度应该足够:scipy.special直接在binom的C扩展层中实现并进行一些调整以减少小输入的精度问题。 orthogonal_eval直接在Python中实现小输入内容,并且在不通过misc本身的情况下使用special调用 - 所以对于编程这些内容的人来说,有一些重新发明的轮子。由于它们在Python层和C层之间混合和匹配函数调用,因此存在一些精度差异并不奇怪。