How to find the sign of a value?

Blitz3D Forums/Blitz3D Programming/How to find the sign of a value?

WolRon(Posted 2004) [#1]
My brain isn't working at the moment. What's a very simple way to determine the sign of a variable?
I'm thinkinf of somehow using the ABS() function but


Ironically, it came to me as I typed this question!
If ABS(variable) = variable
  ;variable is positive (or zero?)
Else
  ;variable is negative
EndIf



Jeremy Alessi(Posted 2004) [#2]
varPositive = var > 0



WolRon(Posted 2004) [#3]
Doing speedtests though, I see that's it's much faster to just check if the variable is greater than zero.
starttime = MilliSecs()
For iter = 1 To 100000000
If Abs(variable) = variable
  ;variable is positive
Else
  ;variable is negative
EndIf
Next
Print MilliSecs() - starttime
starttime = MilliSecs()
For iter = 1 To 100000000
If variable > 0
  ;variable is positive
Else
  ;variable is negative
EndIf
Next
Print MilliSecs() - starttime
WaitKey()
End

711
266



Michael Reitzenstein(Posted 2004) [#4]
Have you tried the Sgn( ) function?


MSW(Posted 2004) [#5]
modified WolRons little test code:

variable% = 1


;first routine roughly 697 milliseconds
;WolRons routine

starttime = MilliSecs()
For iter = 1 To 100000000
If Abs(variable) = variable
  ;variable is positive
Else
  ;variable is negative
EndIf
Next
Print MilliSecs() - starttime


;second routine about 289 milliseconds
;Jeremys routine

starttime = MilliSecs()
For iter = 1 To 100000000
If variable > 0
  ;variable is positive
Else
  ;variable is negative
EndIf
Next
Print MilliSecs() - starttime


;third routine about 756 milliseconds
;Micheals

starttime = MilliSecs()
For iter = 1 To 100000000
If Sgn(variable)
  ;variable is positive
Else
  ;variable is negative
EndIf
Next
Print MilliSecs() - starttime


;fourth routine about 253 milliseconds
;Mine ... note: the IF/ELSE results are switched

flagger=%10000000000000000000000000000000

starttime = MilliSecs()
For iter = 1 To 100000000
If (variable And flagger)
  ;variable is negative
Else
  ;variable is positive
EndIf
Next
Print MilliSecs() - starttime


WaitKey()
End


For the most part the ABS() and SGN() routines take more time because of the function call...pushing/popping onto the stack and all that...Jeremy's routine works very well, even would work with floats...All I'm doing is a bitwise check of the bit supposedly containing the integer pos/neg flag...it's a really old trick that is only usefull for integers and won't work with floats.


JazzieB(Posted 2004) [#6]
var > 0 should be var > -1 or var >= 0 as zero is a positive number. The first would return False for zero indicating a negative number, which is wrong of course.


big10p(Posted 2004) [#7]
As has already been said, use the Sgn() function - that's what it's for! I really wouldn't worry about speed issues using it. I doubt this is going to represent any kind of significant bottleneck in your code. :P

Stop looking for problems where there aren't any! :)


Warren(Posted 2004) [#8]
Amazing what eliminating a function call can do. :)

But, as with every performance test, this is pathological. Unless you're doing this test 10's of thousands of times per frame, the speed difference is not really a factor.


Damien Sturdy(Posted 2004) [#9]
im amazed how many people dont know of SGN.. its in all basic's! (well, i hope it is- its in every version i use)

Why would it be slow? cant be slower than a whole lot of "If"!

Cheers.

push and poping?
IF is likely to use as much time!


TomToad(Posted 2004) [#10]
push and poping?
IF is likely to use as much time!

The Sgn function would most likely look something like this (except in machine code and not basic)
Function Sgn%(number#)

If number# < 0 Then Return 0
Return 1

End Function


Which is basically what the routine did before with If a < 0 except that now you're adding the overhead of a function call and you still need to use the If statement to compare the result of the Sgn function. So yes, it would be slower. After some time testing, I've found that it is more than twice as slow.

Now the difference is only a fraction of a millisecond, so for 99% of your programs, it really won't make any performance difference, but if you're using it several times in your main game loop, that small difference could be what determines if your game will run smoothly on your friend's Pentium II 750. :)


Michael Reitzenstein(Posted 2004) [#11]
Sgn is more useful as it returns -1 for a negative number, 0 for 0 and 1 for a positive number - it's not something you can do without a few ifs when inlining.


Warren(Posted 2004) [#12]
Now the difference is only a fraction of a millisecond, so for 99% of your programs, it really won't make any performance difference, but if you're using it several times in your main game loop, that small difference could be what determines if your game will run smoothly on your friend's Pentium II 750. :)

I doubt that. If "Sgn()" is your performance bottleneck, you're done. Ship it.


WolRon(Posted 2004) [#13]
it's a really old trick that is only usefull for integers and won't work with floats.
Signed integers at that.

I doubt that. If "Sgn()" is your performance bottleneck, you're done. Ship it.

Yeah, I know that. But I only did the test to see how large the difference was. There's no harm in knowing which method is faster. If you don't test it, you won't know.


MSW(Posted 2004) [#14]

Why would it be slow? cant be slower than a whole lot of "If"!



It's not exactly all the extra push and pops onto the stack that eats up the CPU cycles...its the jump to the function code, and then the jump back to where the function was called that can really slow things down...as you start getting into cache hit/miss issues :P

course IF/THENs can invoke such speed problems as well...but you end up compounding the problem by exposeing the CPU to more and more jumps through function calls...one of the reasons we have precompilers with macro support :)


it's a really old trick that is only usefull for integers and won't work with floats.

Signed integers at that.



True...but if they arn't signed integers, then there is no need to even check them :)

Anyway, I'd stick with SGN() as it's more then fast enough for most all needs


ashmantle(Posted 2004) [#15]
heh..

this discussion is like.. kinda meaningless...

Its a function, its there, use it..

if I would have to program every tiny function myself everytime I needed something done, I would hate programming.. like some of you said... SGN() is unlikely to be your bottleneck, and if it is, you're doing something horribly wrong. People have been writing games for maaaaany years now, and we left the ancient practice of dreading speed hits with if-then statements long ago.

If you're THAT interested in optimizing, you wouldn't use blitzbasic in the first place.. hardly the fastes language out there.. :)


MSW(Posted 2004) [#16]

If you're THAT interested in optimizing, you wouldn't use blitzbasic in the first place.. hardly the fastest language out there.. :)



Naw, all the more reason to have an intrest in optimization

Even a really badly coded assembler routine can execute slower then a simuler badly coded routine running through the virtual machine of an interpreted language ... computer languages are nothing more then tools, if you don't use them properly, they arn't going to do you much good ... no matter how fast a percived language might be.

And useing them properly doesn't mean you must stick with functions like SGN() for all cases just because the language supplies it...it means to find the best solution to your programing challange and implament it