Vishal
Vishal

Reputation: 73

How to tell if a 32 bit int can fit in a 16 bit short

Using only:

! ~ & ^ | + << >>

I need to find out if a signed 32 bit integer can be represented as a 16 bit, two's complement integer.

My first thoughts were to separate the MSB 16 bits and the LSB 16 bits and then use a mask to and the last 16 bits so if its not zero, it wont be able to be represented and then use that number to check the MSB bits.

An example of the function I need to write is: fitsInShort(33000) = 0 (cant be represented) and fitsInShort(-32768) = 1 (can be represented)

Upvotes: 7

Views: 8037

Answers (5)

cyco130
cyco130

Reputation: 4934

bool fits16(int x)
{
    short y = x;
    return y == x;
}

Just kidding :) Here's the real answer, assuming int is 32 bits and short is 16 bits and two's complement represantation:

Edit: Please see the last edit for the correct answer!

bool fits16(int x)
{
    /* Mask out the least significant word */
    int y = x & 0xffff0000;
    if (x & 0x00008000) {
        return y == 0xffff0000;
    } else {
        return y == 0;
    }
}

Without if statements i beleive that should do it:

return (
    !(!(x & 0xffff0000) || !(x & 0x00008000)) ||
    !((x & 0xffff0000) || (x & 0x00008000))
);

Edit: Oli's right. I somehow thought that they were allowed. Here's the last attempt, with explanation:

We need the 17 most significant bits of x to be either all ones or all zeroes. So let's start by masking other bits out:

int a = x & 0xffff8000; // we need a to be either 0xffff8000 or 0x00000000
int b = a + 0x00008000; // if a == 0xffff8000 then b is now 0x00000000
                        // if a == 0x00000000 then b is now 0x00008000
                        // in any other case b has a different value
int c = b & 0xffff7fff; // all zeroes if it fits, something else if it doesn't
return c;

Or more concisely:

return ((x & 0xffff8000) + 0x8000) & 0xffff7fff;

Upvotes: 8

Emil Romanus
Emil Romanus

Reputation: 794

Here's a solution without casting, if-statements and using only the operators you asked for:

#define fitsInShort(x) !(((((x) & 0xffff8000) >> 15) + 1) & 0x1fffe)

Upvotes: 3

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272517

If a 32-bit number is in the range [-32768,+32767], then the 17 msbs will all be the same.

Here's a crappy way of telling if a 3-bit number is all ones or all zeros using only your operations (I'm assuming that you're not allowed conditional control structures, because they require implicit logical operations):

int allOnes3(int x)
{
    return ((x >> 0) & (x >> 1) & (x >> 2)) & 1;
}

int allTheSame3(int x)
{
    return allOnes3(x) | allOnes3(~x);
}

I'll leave you to extend/improve this concept.

Upvotes: 8

phoxis
phoxis

Reputation: 61910

if (!(integer_32 & 0x8000000))
{
   /* if +ve number */
  if (integer_32 & 0xffff8000)
    /* cannot fit */
  else 
    /* can fit */
}
else if (integer_32 & 0x80000000)
{
  /* if -ve number */
  if ( ~((integer_32 & 0xffff8000) | 0x00007fff))
    /* cannot fit */
  else
    /* can fit */
}

First if Checks for +ve number first by checking the signed bit. If +ve , then it checks if the bit 15 to bit 31 are 0, if 0, then it cannot fit into short, else it can.

The negative number is withing range if bit 15 to 31 are all set (2's complement method representation).

Therefore The second if it is a -ve number, then the bit 15 to 31 are masked out and the remaining lower bits (0 to 14) are set. If this is 0xffffffff then only the one's complement will be 0, which indicates the bit 15 to 31 are all set, therefore it can fit (the else part), otherwise it cannot fit (the if condition).

Upvotes: 0

BlackBear
BlackBear

Reputation: 22979

short fitsInShort(int x)
{
    int positiveShortRange = (int) ((short) 0xffff / (short) 2);
    int negativeShortRange = (int) ((short) 0xffff / (short) 2) + 1;

    if(x > negativeShortRange && x < positiveShortRange)
        return (short) x;
    else
        return (short) 0;
}

Upvotes: 0

Related Questions