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
最佳答案
每当您遇到不知道某些代码在做什么并且在某个解释器中简单地导入父模块并检查代码的执行、文档字符串等并不容易的情况时,那么您有一些选项。
让我来描述两个选项,这两个选项这次结果不是很有帮助,但它们是将来开始解决此类问题的好方法(以便您可以包含这些尝试的输出,以向人们证明您尝试过在这里发布之前的一些东西,并且看起来很喜欢知道这些东西是什么):
您可以使用 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
的系统调用。谷歌搜索这个模块发现我们正在谈论一个共享库,构建为文件 orthogonal_eval.so
我发现了这个 nice page with the source code .你可以看到
binom
的完整函数定义在那里,其中包括对小值公式中涉及的阶乘的标准计算,以及与其他特殊函数的一些近似值(我看到一些名为 cephes.h
的文件中定义的对“Gamma”、“beta”和“lbeta”的调用) )。看起来很标准——如果我需要的话,我可以去挖掘一下
.h
文件和谷歌更多一些,可能会在所有这些的底部找到一个长期存在的特殊函数的 C 库。同时,对于
misc.comb
首先考虑regular documentation这是可用的(而对我来说,它不适用于 binom
)。文档字符串表示可能存在第三个参数,
exact
如果您不想要 float
,可以将其设置为 0 以外的值。被退回。在这种情况下,long
已返回,但您可以转换为 int
如果你愿意。这就解释了精度问题。您可以阅读
orthogonal_eval
怎么样k
相对较小,答案将给出一个整数(整数参数),然后使用舍入误差较小的东西。而comb
只有在你说 exact=1
时才会这样做(或其他任何东西,例如 exact != 0
)。至于
comb
的代码正在执行,好吧,我们可以 view the source这是从 SciPy 文档页面链接的。该函数还利用了来自
scipy.special
的一些辅助函数调用。但是 Python 层和 C 层中调用的混合是不同的,并且近似部分的实现也略有不同。我不确定您需要什么级别的特异性,但我想说,对于大多数用途,这种级别的详细信息应该足够了:
binom
直接在 orthogonal_eval
中的 C 扩展层中实现并进行一些调整以减少小输入的精度问题。 misc
直接在Python中实现小输入的东西并利用special
调用不经过 binom
本身——所以对于编程这些的人来说,有一定程度的重新发明轮子。由于它们在 Python 层和 C 层之间混合和匹配函数调用,因此存在一些精度差异也就不足为奇了。
关于python - scipy.special.binom 和 scipy.misc.comb 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21535852/