Determining if an Int Fits into a Short in C using Bitwise Operators

2

I am tasked with making a function that returns whether or not an int x fits into a short in C (return 1 if it does, 0 otherwise). This would normally be a fairly simple solution, but I'm constrained to using only the following bitwise operators:! ~ & ^ | + << >>.

Here are some more rules:

  • I am only allowed to use a maximum of 8 of these operators.

  • No external libraries are to be included.

  • I'm not allowed to use any conditional statements (so no ifs, whiles, etc).

  • The only variables I can work with are those of type int and I cannot define constants like 0x0000ffff. However, I can use 0x0and 0xff.

  • It is safe to assume ints are 32 bits and shorts are 16 bits.

I understand the basic functionalities of these operators, but am confused on the logic of implementation. Any ideas?

c
binary
int
bit-manipulation
asked on Stack Overflow Feb 7, 2019 by (unknown user) • edited Feb 7, 2019 by (unknown user)

2 Answers

3

Supposing two’s complement, arithmetic right-shift, left-shift that discards overflowing bits, and 32-bit int, then:

x<<16>>16 ^ x

is zero if and only if x fits in a 16-bit short.

Since we are asked to return zero for does-not-fit and one for does-fit, we can return:

! (x<<16>>16 ^ x)

Proof:

If x fits in a short, then x•216 fits in an int, so x<<16 produces that with no overflow, and x<<16>>16 restores x (since arithmetic shift right that only removes zeros is effectively a division with no remainder), after which x ^ x is zero.

If x exceeds a short, then x<<16 overflows (which we assume results in discarding the high bits). Furthermore, its value is one of the values produced by y<<16 for some y that is a short. Then x<<16>>16 must produce the same value as y<<16>>16, which is y, which differs from x, and therefore x<<16>>16 ^ x cannot be zero.

answered on Stack Overflow Feb 7, 2019 by Eric Postpischil • edited Feb 7, 2019 by Eric Postpischil
0

Assuming 2 complements, your original idea to test that all leading but 15 bits are all 0 or all 1 does work.

11111111 11111111 1xxxxxxx xxxxxxxx /* for negative 16 bits int */
00000000 00000000 0xxxxxxx xxxxxxxx /* for positive 16 bits int */

Assuming arithmetic right shift, you can shift right by 15 to eliminate the unknown bits, then only 1s or 0s will remain (if it fits on 15 bits)

Thus x>>15 should then be either 0 or -1.
If it is 0, then !(x>>15) is true.
If it is -1, then !(~(x>>15)) is true.
You can thus test !(x>>15) | !(~(x>>15))
Or you can also write it like that: !(x>>15) | !(~x>>15)

Note that above expressions don't assume 32bits x, and would also work for testing if an int64 would fit into an int16...

There are many other ways...
Since you can also use +, (x>>15)+1 is 0 or 1.
You can then clear the last bit with: ((x>>15)+1)>>1.
x does fit in 16bits int if above expression is all 0 (false), thus you want:

! (((x>>15)+1)>>1)

Up to you to find more expressions...

answered on Stack Overflow Feb 10, 2019 by aka.nice

User contributions licensed under CC BY-SA 3.0