使用中间列表是没有用的,bitstring不是直接转换成整数,所以我不认为它也有用,所以最好的解决方案是直接使用大数字。 让说你想要创建其在十进制表示由宽度宽的图案的N次重复来表示的整数:
与N = 3
,Pattern = 52
,Width = 4
,预期的结果是5200520052
第一个简单的实现,通过移动并添加模式N次计算结果,但对于大N来说效率非常低。下面是一个实现(请注意,为了衡量性能,我避免打印结果,因为否则shell会将整数iolist):
-module (pattern).
-export ([simple/3,perf/4]).
simple(N,Pattern,Width) when is_integer(N), N > 0 ->
simple(N,Pattern,shift(1,Width),0).
simple(0,_,_,R) -> R;
simple(X,P,Shift,R) -> simple(X-1,P,Shift,R*Shift+P).
shift(X,0) -> X;
shift(X,N) -> shift(10*X,N-1).
perf(Type,N,P,S) ->
{T,_} = timer:tc(?MODULE,Type,[N,P,S]),
T.
这样,你得到的结果:
1> pattern:simple(7,52,3).
52052052052052052052
2> pattern:simple(7,52,2).
52525252525252
3> pattern:perf(simple,1000,5,1).
0
4> pattern:perf(simple,10000,5,1).
63000
5> pattern:perf(simple,100000,5,1).
1810000
6> pattern:perf(simple,1000000,5,1).
309522533
的时间很长(5分钟1000000)和成倍增加。
减少这一点的想法是要成倍减少操作的次数。这个智能版本是使用图案至极在宽度在每次迭代增加一倍,并在需要时在当前结果级联(I有使用N的分解在2的幂):
-module (pattern).
-export ([simple/3,smarter/3,perf/4]).
simple(N,Pattern,Width) when is_integer(N), N > 0 ->
simple(N,Pattern,shift(1,Width),0).
simple(0,_,_,R) -> R;
simple(X,P,Shift,R) -> simple(X-1,P,Shift,R*Shift+P).
shift(X,0) -> X;
shift(X,N) -> shift(10*X,N-1).
perf(Type,N,P,S) ->
{T,_} = timer:tc(?MODULE,Type,[N,P,S]),
T.
smarter(1,Pattern,_Width) -> Pattern;
smarter(N,Pattern,Width) when is_integer(N), N > 0 ->
smarter(N,Pattern,shift(1,Width),0).
smarter(1,Pattern,Shift,R) ->
R * Shift + Pattern;
smarter(X,Pattern,Shift,R) when (X rem 2) == 0 ->
smarter(X div 2, Shift * Pattern + Pattern, Shift * Shift, R);
smarter(X,Pattern,Shift,R) ->
smarter(X div 2, Shift * Pattern + Pattern, Shift * Shift, R * Shift + Pattern).
的结果是多更好:5万秒1000000,仍然增加n * n,由于乘法。
1> pattern:smarter(7,52,4).
52005200520052005200520052
2> pattern:smarter(7,9,1).
9999999
3> pattern:perf(smarter,1000,5,1).
0
4> pattern:perf(smarter,10000,5,1).
0
5> pattern:perf(smarter,100000,5,1).
125000
6> pattern:perf(smarter,500000,5,1).
1279007
7> pattern:perf(smarter,1000000,5,1).
5117000
你为什么要这么做? –
@SteveVinoski我后来意识到这是解决我的问题的错误方式,但是那说了,我仍然想知道如何去做我想做的事情。所以我不再有一个很好的理由超越“好奇心”。 – Tommy