根据jonalm的评论进行编辑:
jonalm: N~3^n而不是n~3^N。其中N是a中的最大元素,n是a的元素数量。
n约为2^20。如果N约为3^n,则N约为3^(2^20) > 10^(500207)。科学家估计(http://www.stormloader.com/ajy/reallife.html),宇宙中只有大约10^87个粒子。因此,计算机无法处理大小为10^(500207)的int型变量(天真的方法)。
jonalm: 不过我对你定义的pv()函数有点好奇。(我无法运行它,因为text.find()未定义(猜测它在另一个模块中)。)这个函数如何工作,它有什么优势?
pv是我编写的一个小助手函数,用于调试变量的值。它的工作方式类似于print(),但当你输入pv(x)时,它会同时打印出字面上的变量名(或表达式字符串)、一个冒号和变量的值。
如果你放进去
import traceback
def pv(var):
(filename,line_number,function_name,text)=traceback.extract_stack()[-2]
print('%s: %s'%(text[text.find('(')+1:-1],var))
x=1
pv(x)
在脚本中,你应该得到:
x: 1
使用 pv 而不是 print 的小优势在于它节省了您的打字时间。您不必再写出以下内容:
print('x: %s'%x)
你可以直接放下。
pv(x)
当有多个变量需要跟踪时,给变量贴上标签会很有帮助。我只是厌倦了一遍又一遍地写出它们。
pv函数通过使用traceback模块来查看调用pv函数本身的代码行。 (参见
http://docs.python.org/library/traceback.html#module-traceback)该行代码以字符串形式存储在变量text中。 text.find()是对通常的字符串方法find()的调用。例如,如果
text='pv(x)'
那么
text.find('(') == 2
text[text.find('(')+1:-1] == 'x'
我假设 n ~ 3^N,且 n ~ 2 ** 20。
这个想法是在模 N 的情况下工作。这可以减少数组的大小。第二个想法(当 n 很大时非常重要)是使用 numpy ndarrays 的 'object' 类型,因为如果使用整数 dtype,可能会导致超过允许的最大整数大小。
import traceback
import numpy as np
def pv(var):
(filename,line_number,function_name,text)=traceback.extract_stack()[-2]
print('%s: %s'%(text[text.find('(')+1:-1],var))
您可以将n更改为2 ** 20,但是下面我展示小n的情况,以便输出更易于阅读。
n=100
N=int(np.exp(1./3*np.log(n)))
pv(N)
a=np.random.randint(N,size=n)
b=np.random.randint(N,size=n)
pv(a)
pv(b)
wa存储了a中0、1、2、3的数量,
wb存储了b中0、1、2、3的数量。
wa=np.bincount(a)
wb=np.bincount(b)
pv(wa)
pv(wb)
result=np.zeros(N,dtype='object')
将以下文本翻译为中文:
将0看作一个代币或筹码。1、2、3同理。
将wa=[24 28 28 20]看作意味着有一个袋子,里面有24个0代币,28个1代币,28个2代币和20个3代币。
你有一个wa袋和一个wb袋。当你从每个袋子中取出一个代币时,你将它们“相加”并形成一个新的代币。你对答案进行“模运算”(模N)。
想象一下从wb袋中取出一个1代币,并将其与wa袋中的每个代币相加。
1-chip + 0-chip = 1-chip
1-chip + 1-chip = 2-chip
1-chip + 2-chip = 3-chip
1-chip + 3-chip = 4-chip = 0-chip (we are mod'ing by N=4)
由于wb袋中有34个1芯片,当你将它们与wa=[24 28 28 20]袋中的所有芯片相加时,你会得到:
34*24 1-chips
34*28 2-chips
34*28 3-chips
34*20 0-chips
这只是由于34个1芯片造成的部分计数。您还需要处理wb袋中的其他类型芯片,但以下内容展示了使用的方法:
for i,count in enumerate(wb):
partial_count=count*wa
pv(partial_count)
shifted_partial_count=np.roll(partial_count,i)
pv(shifted_partial_count)
result+=shifted_partial_count
pv(result)
这是最终结果:2444个0,2504个1,2520个2,2532个3。
if n>1000:
print('n is too large to run the check')
else:
c=(a[:]+b[:,np.newaxis])
c=c.ravel()
c=c%N
result2=np.bincount(c)
pv(result2)
assert(all(r1==r2 for r1,r2 in zip(result,result2)))