Page 1 of 1

Counter without If/Endif

Posted: Tue Sep 27, 2005 2:54 pm
by va!n
Code updated For 5.20+

Using % (MODULO) to count any value! This is a nice way to optimize and "maybe speed up!?" your counter without the use of any If/Endif check! 8)

Original version...

Code: Select all

lCountTo   = 31      ; Only change the val (max you want to count)
lCountStep = 1

Repeat
 lCountResult = lCountResult + lCountStep 

 If lCountResult > lCountTo
  lCountResult = 0
 EndIf
 
 Debug lCountResult
 Delay(100)
ForEver
Optimized version....

Code: Select all

lCountTo   = 31
lCountStep = 1

Repeat
 lCountResult = (lCountResult % lCountTo) + lCountStep
 Debug lCountResult
 Delay(100)
ForEver
Please dont change lCountStep! You can try to set "lCountStep = 2" and check the results... one loop the resutls are even and in the next loop they arent... maybe usefull or any special situation....

Posted: Tue Sep 27, 2005 6:12 pm
by fweil
Looks nice in reading, but use of % have a cost in CPU time I guess.

Rgrds

Posted: Tue Sep 27, 2005 7:35 pm
by Fred
yes, it uses a division op, which is a very expensive one. Speed wise, i think the if/endif method will beat it.

Posted: Tue Sep 27, 2005 9:08 pm
by va!n
Thanks for your reply, fweil and Fred!


@Fred:
You are right, the If/Endif methode is lightyears faster! ;)

I had some time to do a small speed test.... here are the results...

a) MODULO = 266 ms :cry:
b) If/Endif = 47 ms :)

Code: Select all

lCountTo   = 31      ; Only change the val (max you want to count)
lCountStep = 1

StartTime = GetTickCount_()

 For i = 0 To 10000000 
  lCountResult = (lCountResult % lCountTo) + lCountStep
  Debug lCountResult 
 Next
 
MessageRequester("Result:",Str(GetTickCount_()-StartTime))

Code: Select all

lCountTo   = 31      ; Only change the val (max you want to count)
lCountStep = 1

StartTime = GetTickCount_()
 For i = 0 To 10000000 
  lCountResult = lCountResult + lCountStep

  If lCountResult > lCountTo
   lCountResult = 0
  EndIf
  
  Debug lCountResult
 Next
MessageRequester("",Str(GetTickCount_()-StartTime))

Posted: Wed Sep 28, 2005 9:49 am
by GedB
If you are using on of the powers of 2, like 8, 16, 32 or 64 you can get the result by masking with an &, which is very quick.

Using the following code I get the following results:
  • And: 31
    Mod: 375
    If: 47

Code: Select all

lCountToMask   = %00011111     ; 32 in binary
lCountStep = 1

StartTime = GetTickCount_()

 For i = 0 To 10000000
  lCountResult = (lCountResult & lCountToMask) + lCountStep
  Debug lCountResult
 Next
 
MessageRequester("And Result:",Str(GetTickCount_()-StartTime)) 

lCountTo   = 32      ; Only change the val (max you want to count)
lCountStep = 1

StartTime = GetTickCount_()

 For i = 0 To 10000000
  lCountResult = (lCountResult % lCountTo) + lCountStep
  Debug lCountResult
 Next
 
MessageRequester("Mod Result:",Str(GetTickCount_()-StartTime)) 

lCountTo   = 32      ; Only change the val (max you want to count)
lCountStep = 1

StartTime = GetTickCount_()
 For i = 0 To 10000000
  lCountResult = lCountResult + lCountStep


  If lCountResult > lCountTo
   lCountResult = 0
  EndIf
 
  Debug lCountResult
 Next
MessageRequester("If Result:",Str(GetTickCount_()-StartTime)) 


Posted: Wed Sep 28, 2005 10:38 am
by va!n
here are my results... (x times tested and same results)

And: 47
Mod: 281
If: 47

Posted: Wed Sep 28, 2005 1:55 pm
by GedB
So theres no reason to obfuscate your code for the sake of performance.

The simplest code is a couple of nested fors. The codes intention couldn't be clearer and I get a speed result of 32.

Code: Select all

lCountTo   = 32      ; Only change the val (max you want to count)
#lCountStep = 1

StartTime = GetTickCount_()
 For i = 0 To 10000000 / lCountTo
  For j = 1 To lCountTo Step #lCountStep 
    Debug j
  Next j
 Next i
MessageRequester("For Result:",Str(GetTickCount_()-StartTime))