Edenia
Edenia

Reputation: 2488

Compare "if between" with bitwise operators instead of logical

Okay i know this is a pretty mean task from which i got nightmares but maybe ..i'll crack that code thanks to someone of you.

I want to compare if number is between 0 and 10 with bitwise operators. Thats the thing.. it is between 0 and 10 and not for example between 0 and 2, 0 and 4, 0 and 8 and so on..

Reference for number/binary representation with 0-4 bits. (little endian)

0 0

1 1

2 10

3 11

4 100

5 101

6 110

7 111

8 1000

9 1001

10 1010


11 1011

12 1100

13 1101

14 1110

15 1111


Trying to figure out something like if(((var & 4) >> var) + (var & 10))

Upvotes: 3

Views: 2358

Answers (4)

Abhijeet Parmar
Abhijeet Parmar

Reputation: 11

bool b1 = CheckCycleStateWithinRange(cycleState, 0b0, 0b1010); // Note *: 0b0 = 0 and 1010 = 10

bool CheckCycleStateWithinRange(int cycleState, int minRange, int maxRange) const
{
   return ((IsGreaterThanEqual(cycleState, minRange) && IsLessThanEqual(cycleState, maxRange)) ? true : false );
}

int IsGreaterThanEqual(int cycleState, int limit) const
{
   return ((limit + (~cycleState + 1)) >> 31 & 1) | (!(cycleState ^ limit));
}

int IsLessThanEqual(int cycleState, int limit) const
{
   return !((limit + (~cycleState + 1)) >> 31 & 1) | (!(cycleState ^ limit));
}

Upvotes: 0

Falk Hüffner
Falk Hüffner

Reputation: 5040

When addition is allowed and the range is 0..15, a simple solution is

(v - 11) & ~7

which is nonzero when v is in the range 0..10. Using shifts instead, you can use

(1<<10) >> v

which is also nonzero if the input is in the range 0..10. If the input range is unrestricted and the shift count is modulo 32, like on most CPUs, you can use

((1<<11) << ~v) | (v & ~15)

which is nonzero if the input is not in the range (the opposite is difficult since already v == 0 is difficult with only bitops). If other arithmetic operations are allowed, then

v / 11

can be used, which is also nonzero if the input is not in the range.

Upvotes: 0

Jubatian
Jubatian

Reputation: 2191

I attempt to solve it with bitwise operators only (no addition).

The expression below will evaulate to nonzero if the number (v) is out of the 0 - 10 inclusive range:

(v & (~0xFU)) |
( ((v >> 3) & 1U) & ((v >> 2) & 1U) ) |
( ((v >> 3) & 1U) & ((v >> 1) & 1U) & (v & 1U) )

The first line is nonzero if the number is above 15 (any higher bit than the first four is set). The second line is nonzero if in the low 4 bits it is between 12 and 15 inclusive. The third line is nonzero if in the low 4 bits the number is either 11 or 15.

It was not clear in the question, but if the number to test is limited between the 0 - 15 inclusive range (only low 4 bits), then something nicer is possible here:

  ((~(v >> 3)) & 1U) |
( ((~(v >> 2)) & 1U) & (( ~v      ) & 1U) ) |
( ((~(v >> 2)) & 1U) & ((~(v >> 1)) & 1U) )

First line is 1 if the number is between 0 and 7 inclusive. Second line is 1 if the number is one of 0, 2, 8 or 10. Third line is 1 if the number is one of 0, 1, 8 or 9. So OR combined the expression is 1 if the number is between 0 and 10 inclusive. Relating this solution, you may also check out the Karnaugh map, which can assist in generating these (and can also be used to prove there is no simpler solution here).

I don't think I could get any closer stricly using only bitwise operators in a reasonable manner. However if you can use addition it becomes a lot simpler as Pat's solution shows it.

Upvotes: 2

pat
pat

Reputation: 12749

Assuming that addition is allowed, then:

(v & ~0xf) | ((v+5) & ~0xf)

is non-zero if v is out-of-range. The first term tests if v is outside the range 0..15, and the second shifts the unwanted 11, 12, 13, 14, 15 outside the 0..15 range.

Upvotes: 1

Related Questions