How to find the sign of a value?
Blitz3D Forums/Blitz3D Programming/How to find the sign of a value?
| ||
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 |
| ||
varPositive = var > 0 |
| ||
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 |
| ||
Have you tried the Sgn( ) function? |
| ||
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. |
| ||
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. |
| ||
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! :) |
| ||
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. |
| ||
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! |
| ||
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. :) |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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 |
| ||
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.. :) |
| ||
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 |