... und mit einem anderen Algo
Der Euklidische Algorithmus ist einen Tacken schneller.
Hier einmal mit und ohne ASM-Optimierungen
Code: Alles auswählen
Procedure FindggT(a,b)
Protected m=a
Protected n=b
Protected s=1
Protected t=0
Protected u=0
Protected v=1
While n>0
q=Round(m/n,0) ;Der Quotient wird abgerundet
r=m-q*n
m=n
n=r
tmp=u
u=s-q*u
s=tmp
tmp=v
v=t-q*v
t=tmp
Wend
ProcedureReturn m
EndProcedure
Procedure.l gcd(m.l, n.l)
Protected k.l = 0
If n < 0 : n * (-1) : EndIf
If m < 0 : m * (-1) : EndIf
While (m % 2 = 0 And n % 2 = 0)
m >> 1
n >> 1
k + 1
Wend
If n % 2 = 0
Swap m, n
EndIf
While m <> 0
While (m % 2 = 0)
m >> 1
Wend
If m < n
Swap m, n
EndIf
m - n
Wend
ProcedureReturn n * (1 << k)
EndProcedure
Procedure.l ggT(a.l, b.l) ; euclid
Protected temp.l
If a < 0
a = -a
EndIf
If b < 0
b = -b
EndIf
While (b > 0)
temp = b
b = a % b
a = temp
Wend
ProcedureReturn a
EndProcedure
Procedure.l ggTAsm(a.l, b.l) ; euclid in asm
!MOV eax, [esp+4] ; copy a to eax
!AND eax, eax ; set flags
!JGE @f ; IF eax >= 0 then jump to @@
!NEG eax ; ELSE negate eax
!@@:
!MOV ebx, [esp+8] ; copy b to ebx
!AND ebx, ebx ; set flags
!JGE @f ; IF ebx >= 0 then jump to @@
!NEG ebx ; ELSE negate ebx
!@@:
!_ggtMyAsmWhile:
!AND ebx, ebx ; set flags
!JLE _ggtMyAsmWend ; jump to end on 0
; c = b
!MOV ecx, ebx ; save b to ecx
; b = a % b
!XOR edx, edx ; extend sign to edx with 0
!IDIV ebx ; div edx:eax / ebx
!MOV ebx, edx ; move rest to b
; a = c
!MOV eax, ecx ; move temp to a
!JMP _ggtMyAsmWhile ; loop
!_ggtMyAsmWend:
ProcedureReturn ; return eax
EndProcedure
#N = 999999
Delay(0)
RandomSeed(1000)
time1 = ElapsedMilliseconds()
For z = 0 To #N
FindggT(Random(10000000)+1,Random(10000000)+1)
Next
time1 = ElapsedMilliseconds() - time1
RandomSeed(1000)
time2 = ElapsedMilliseconds()
For z = 0 To #N
gcd(Random(10000000)+1,Random(10000000)+1)
Next
time2 = ElapsedMilliseconds() - time2
RandomSeed(1000)
time3 = ElapsedMilliseconds()
For z = 0 To #N
ggT(Random(10000000)+1,Random(10000000)+1)
Next
time3 = ElapsedMilliseconds() - time3
RandomSeed(1000)
time4 = ElapsedMilliseconds()
For z = 0 To #N
ggTAsm(Random(10000000)+1,Random(10000000)+1)
Next
time4 = ElapsedMilliseconds() - time4
SetClipboardText("FindggT: "+Str(time1)+" gcd: "+Str(time2)+ " ggt: " + Str(time3)+ " ggtAsm: " + Str(time4))
MessageRequester("", GetClipboardText())
Speedtest bei mir:
FindggT: 1375 gcd: 437 ggt: 375 ggtAsm: 344
Aber vielleicht lässt sich gcd in asm noch so gut optimieren, dass er fixer ist ?
P.S.: gcd/ggt/ggtasm funktionieren auch mit negativen Zahlen (werden als positive genutzt) im Gegensatz zu findggt