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
答案 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 documentation的view 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层之间混合和匹配函数调用,因此存在一些精度差异并不奇怪。