Getting the sign of a number

Share your advanced PureBasic knowledge/code with the community.
Dr. Dri
Enthusiast
Enthusiast
Posts: 243
Joined: Sat Aug 23, 2003 6:45 pm

Getting the sign of a number

Post by Dr. Dri »

Code updated For 5.20+ (As PB supported)

since pb doesn't fully support boolean expressions, i have to write this annoying code :lol:

Code: Select all

Procedure Sgn(x.l)
  ProcedureReturn Bool((x > 0 Or #False) - (x < 0 Or #False))
EndProcedure

Procedure SgnF(x.f)
  ProcedureReturn Bool((x > 0 Or #False) - (x < 0 Or #False))
EndProcedure

Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)

Debug SgnF(-5.0)
Debug SgnF(-0.0)
Debug SgnF( 5.0)
Dri :lol:
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

How about...

Code: Select all

Procedure Sgn(a.l)
   ProcedureReturn a >> 31 & 1
EndProcedure

Procedure SgnF(a.f)
   ProcedureReturn Int(a) >> 31 & 1
EndProcedure
Not sure if the SgnF is all that fast because of the Int()
Last edited by Xombie on Sun Oct 02, 2005 12:57 am, edited 1 time in total.
Dr. Dri
Enthusiast
Enthusiast
Posts: 243
Joined: Sat Aug 23, 2003 6:45 pm

Post by Dr. Dri »

doesn't work :?

Code: Select all

Procedure Sgn(a.l)
   ProcedureReturn a >> 31 & 1
EndProcedure

Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)
Dri
Xombie
Addict
Addict
Posts: 898
Joined: Thu Jul 01, 2004 2:51 am
Location: Tacoma, WA
Contact:

Post by Xombie »

It's always been my understanding that 0 can neither be positive or negative. So zero has no sign. Some math majors want to help me out on this one?

However that fudges my SgnF function for numbers less than one >_>
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

But those function are not valid for .b or .w
Here i made one: viewtopic.php?t=8121
But here are 2 different functions for it in which it is improved in size and speed:

Code: Select all

Procedure.b Sgn(n.f)
  !fld dword[esp] ;push FPU stack, and load value to st0
  !fstp st1 ;leaves popped FPU stack while maintaining value in st0
  !ftst   ;test value for update FPU flags.
  !fnstsw ax  ;transfers FPU status word to ax
  !fwait
  !sahf    ;transfers ah to CPU flags.
  !seta al ;if positive al=1, else al=0
  !jnc near @f;if negative jump, else:
  !dec al
  !@@:movsx eax,al ;return and finish
  ProcedureReturn
EndProcedure

;Prove it:
r.f=7
Debug Sgn(0.000094)
Debug Sgn(-v.b)
Debug Sgn(-r.f)
Debug ""
For t.w=-20 To 20
  Debug Sgn(t.w)
Next
Last edited by Psychophanta on Mon Oct 03, 2005 11:28 pm, edited 1 time in total.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Dr. Dri
Enthusiast
Enthusiast
Posts: 243
Joined: Sat Aug 23, 2003 6:45 pm

Post by Dr. Dri »

Psychophanta wrote:But those function are not valid for .b or .w
I agree, it's like using a byte or a word with hex(). You need & $FF or $FFFF...

Dri
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Nope, i was wrong!
Your functions works for .b and .w too.

But not needed 2 separate functions; you can resume it in one only function for all PB native types:

Code: Select all

Procedure Sgn(x.f) 
  ProcedureReturn (x > 0 Or #False) - (x < 0 Or #False) 
EndProcedure
However, even it seems to work, that code is not correct for PB specifications :?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

If you want something a bit faster, that only works for integers you can use this:

Code: Select all

Procedure Sgn(a.l)
  MOV eax, [esp]
  XOR ebx, ebx
  AND eax, eax
  SETNZ bl
  SAR eax, 31
  OR eax, ebx
  ProcedureReturn
EndProcedure
Killswitch
Enthusiast
Enthusiast
Posts: 731
Joined: Wed Apr 21, 2004 7:12 pm

Post by Killswitch »

0 can't be postive or negative, but 1-0 and 1+0 are equal so it doesn't matter. x^0 = 1, including 0^0=1 - I've always found that weird. Just don't ever divide anything by zero - things get horribly complex then.
~I see one problem with your reasoning: the fact is thats not a chicken~
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Post by va!n »

what about this way?

Code: Select all

Procedure Sgn(x.l)
 If x.l < 0 
  result = #True
 Else
  result = #False
 EndIf
 ProcedureReturn result 
EndProcedure

Procedure SgnF(x.f)
 If x.f < 0 
  result = #True
 Else
  result = #False
 EndIf
 ProcedureReturn result
EndProcedure

Debug Sgn(-5)
Debug Sgn(-0)
Debug Sgn( 5)

Debug SgnF(-5.0)
Debug SgnF(-0.0)
Debug SgnF( 5.0)
Btw, Debug SgnF(-0.0) returns #FALSE, because 0 cant be negative or positive!
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
Dr. Dri
Enthusiast
Enthusiast
Posts: 243
Joined: Sat Aug 23, 2003 6:45 pm

Post by Dr. Dri »

@Pupil
Nice example but i'm an ASM begginer so i don't understand :lol:
but it works very well ^^

@va!n
My idea was to return a -1|0|1 which would mean neg|nul|pos

Dri
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post by MikeB »

Psychophanta gave us two routines, as far as I can see the first one works but the second one is wrong for -0.xxxx. Or at least it is wrong for -1/7 which is what I used.

MikeB
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

MikeB wrote:Psychophanta gave us two routines, as far as I can see the first one works but the second one is wrong for -0.xxxx. Or at least it is wrong for -1/7 which is what I used.

MikeB
Oopps!
You're right. Thanx to correct me. I was at the point to add it to my 'tested' collection.
Well, then i gave you only the first one :oops: :)
But here is one much faster, and smaller.
It is tricky, and it has an only problem: if you give it a '-0' value, it will result as '-1'. But apart of that, it works wonderfully:

Code: Select all

Procedure.b Sgn(n.f)
  !mov eax,dword[esp]
  !test eax,eax
  !jz @f
  !sar eax,31
  !bts eax,0
  !@@:
  ProcedureReturn
EndProcedure
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
va!n
Addict
Addict
Posts: 1104
Joined: Wed Apr 20, 2005 12:48 pm

Post by va!n »

@Psychophanta
Respect! Very nice! Works fine here! Keep it on! :wink:
va!n aka Thorsten

Intel i7-980X Extreme Edition, 12 GB DDR3, Radeon 5870 2GB, Windows7 x64,
Post Reply