现在<script src="http://code.angularjs.org/1.2.10/angular.js"></script>
<script src="http://bouil.github.io/angular-google-chart/ng-google-chart.js"></script>
<div ng-app='myApp'><div ng-controller="MainCtrl">
<div style="float:right;position:relative;z-index:100;background:#f1f1f1;padding-top:40px">
<p>
Software: <input type=range min=10000 max=100000 value={{aa}} ng-model="aa" ng-change="chart.data[1][1]=1*aa;chart.data[1][2]=1*aa"> {{aa}}
</p>
<p>
Hardware: <input type=range min=10000 max=100000 value={{bb}} ng-model="bb" ng-change="chart.data[2][1]=1*bb;chart.data[2][2]=1*bb">{{bb}}
</p>
<p>
Services: <input type=range min=10000 max=100000 value={{cc}} ng-model="cc" ng-change="chart.data[3][1]=1*cc;chart.data[3][2]=1*cc">{{cc}}
</p>
</div>
<div google-chart chart="chart">
</div>
</div></div>
确实比ad-hoc实施更快,这是确凿的吗?
根据旧答案Statistics: combinations in Python,此自制函数在计算组合scipy.misc.comb
时比scipy.misc.comb
快:
nCr
但是在我自己的机器上运行一些测试之后,使用这个脚本似乎并非如此:
def choose(n, k):
"""
A fast way to calculate binomial coefficients by Andrew Dalke (contrib).
"""
if 0 <= k <= n:
ntok = 1
ktok = 1
for t in xrange(1, min(k, n - k) + 1):
ntok *= n
ktok *= t
n -= 1
return ntok // ktok
else:
return 0
我得到以下输出:
from scipy.misc import comb
import random, time
def choose(n, k):
"""
A fast way to calculate binomial coefficients by Andrew Dalke (contrib).
"""
if 0 <= k <= n:
ntok = 1
ktok = 1
for t in xrange(1, min(k, n - k) + 1):
ntok *= n
ktok *= t
n -= 1
return ntok // ktok
else:
return 0
def timing(f):
def wrap(*args):
time1 = time.time()
ret = f(*args)
time2 = time.time()
print '%s function took %0.3f ms' % (f.__name__, (time2-time1)*1000.0)
return ret
return wrap
@timing
def test_func(combination_func, nk):
for n,k in nk:
combination_func(n, k)
nk = []
for _ in range(1000):
n = int(random.random() * 10000)
k = random.randint(0,n)
nk.append((n,k))
test_func(comb, nk)
test_func(choose, nk)
时间分析测试是否显示新$ python test.py
/usr/lib/python2.7/dist-packages/scipy/misc/common.py:295: RuntimeWarning: overflow encountered in exp
vals = exp(lgam(N+1) - lgam(N-k+1) - lgam(k+1))
999
test_func function took 32.869 ms
999
test_func function took 1859.125 ms
$ python test.py
/usr/lib/python2.7/dist-packages/scipy/misc/common.py:295: RuntimeWarning: overflow encountered in exp
vals = exp(lgam(N+1) - lgam(N-k+1) - lgam(k+1))
999
test_func function took 32.265 ms
999
test_func function took 1878.550 ms
比ad-hoc scipy.misc.comb
函数更快?我的测试脚本是否有任何错误导致时间安排不准确的?
为什么choose()
现在更快?这是因为一些scipy.misc.comb
/ cython
包裹技巧?
在@WarrenWeckesser评论之后:
使用c
时使用默认浮点近似值,由于浮点溢出,计算中断。
(有关文档,请参阅http://docs.scipy.org/doc/scipy-0.16.0/reference/generated/scipy.misc.comb.html)
当使用scipy.misc.comb()
进行测试时,使用下面的函数计算长整数而不是浮点数,计算1000种组合时速度要慢得多:
exact=True
[OUT]:
@timing
def test_func(combination_func, nk):
for i, (n,k) in enumerate(nk):
combination_func(n, k, exact=True)
答案 0 :(得分:1)
参考scipy.misc.comb的源代码,结果的更新例程是:
val = 1
for j in xrange(min(k, N-k)):
val = (val*(N-j))//(j+1)
return val
而您建议的更新例程是:
ntok = 1
ktok = 1
for t in xrange(1, min(k, n - k) + 1):
ntok *= n
ktok *= t
n -= 1
return ntok // ktok
我猜测SciPy实现速度较慢的原因是由于子程序在每次迭代时都涉及整数除法,而你的子句只在return语句中调用一次除法。