使用中間列表是沒有用的,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