gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Signed Integer

#170637 - brave_orakio - Fri Oct 09, 2009 2:25 am

Hi guys. A question.

Which bit contains the information for the sign of an int? I want to use some bitwise operations to brinmg down a signed integer to 3 values. -1, 0 and 1.

if it was just 0 and 1 all I do is

Code:


intVal &= 1



So this becomes either 0 or 1 no problem. but this

Code:


intVal &= -1



doesn't seem to work so I decided to try to preserve the bit containing the sign first before working on the rest of the integer.
_________________
help me

#170638 - elhobbs - Fri Oct 09, 2009 2:58 am

-1 is 0xFFFFFFFF. So, anything & -1 will equal the original value. & 0x80000000 will test for negative on a 32bit signed int.

edit: changed "&=" to "&"


Last edited by elhobbs on Fri Oct 09, 2009 5:50 pm; edited 1 time in total

#170640 - brave_orakio - Fri Oct 09, 2009 5:23 am

Thanks, I'll try that out!
_________________
help me

#170666 - keldon - Sat Oct 10, 2009 8:42 am

If you absolutely must:

Code:

#define IS_ZERO( v )      ( !(v) )
#define IS_NEGATIVE( v )   ( u32( (v) ) >> 31 )
#define IS_POSITIVE( v )   ( IS_NEGATIVE( -(v) ) && !IS_ZERO( (v) ) )

intVal = IS_POSITIVE( intVal ) - IS_NEGATIVE( intVal );

#170668 - brave_orakio - Sat Oct 10, 2009 9:42 am

Nice! thanks! Another question though, because I ran into something nasty with my divides:

why is this -1?
Code:

intVal = -54>>6;


shouldn`t it be equal to 0?
_________________
help me

#170669 - Cearn - Sat Oct 10, 2009 12:32 pm

brave_orakio wrote:
Code:
intVal = -54>>6;


shouldn`t it be equal to 0?


No. Bit-shifts are still primarily bit-shifts. That you can use them in a division-like capacity is just an accident of how numbers are represented. In negative numbers, the higher bits are all 1. When you shift-right, these shift into the lower bits. If you shift out all the 'real' bits of a number, the result is all 1s, that is, 0xFFFFFFFF == -1. Effectively, div-by-rightshift always rounds to -infinity (whereas normal integer division rounds to 0).

Code:
// In 16 bits
-54 = 0xFFCA = 1111 1111 1100 1010

1111 1111 1100 1010 >> 6 = 1111 1111 1111 1111 = -1.


keldon wrote:
Code:

#define IS_POSITIVE( v )   ( IS_NEGATIVE( -(v) ) && !IS_ZERO( (v) ) )

Note that the IS_ZERO part doesn't actually do anything here and can safely be removed. For a threeway sign, this is enough:
Code:
//! Returns -1 for x<0, 0 for x==0, and +1 for x>0.
static inline int sign3(int x)
{    return (x>>31) - (-x>>31 );    }

#170670 - keldon - Sat Oct 10, 2009 12:59 pm

--- never mind ---

But yes, 0 >> 31 == 0; duh!

#170683 - brave_orakio - Mon Oct 12, 2009 3:03 am

Ah, I see, thanks!
_________________
help me

#170861 - elyk1212 - Sat Oct 24, 2009 2:10 am

Yeah. If you're variable is a regular int, shifting is signed. So you can right shift till the cows come home, and you'll still get a 1 in the MSB (the sign bit).

But.... If it is an unsigned variable, the >> and << will translate to an unsigned shift operation, you were perhaps expecting.

So maybe as an exercise in fun:

try:
Code:

int si = -something;
unsigned int i = -something;


and try printing these out after/during some shift operations and see the difference.
_________________
"Turn from evil and do good; seek peace and pursue it." Psalm 34:14

Like art? Just some wallpapers I do in my free time:
http://www.razzlegames.com/wallpaper/