-2

So i am working on this method, but am restricted to using ONLY these operators:

<<, >>, !, ~, &, ^, |, +

I need to find if a given int parameter can be represented using 2's complement arithmetic in a given amount of bits.

Here is what I have so far:

int validRange(int val, int bits){
    int minInRange = ~(1<<(bits + ~0 ))+1;   //the smallest 2's comp value possible with this many bits
    int maxInRange = (1<<(bits+~0))+~0;  //largest 2's comp value possible 
    ..........
}

This is what I have so far, and all I need to do now is figure out how to tell if minInRange <= val <=maxInRange. I wish I could use the greater than or less than operator, but we are not allowed. What is the bitwise way to check this?

Thanks for any help!

Team. Coco
  • 85
  • 2
  • 9
  • Do you have to deal with negative values? – user3386109 Feb 06 '17 at 21:36
  • Yup, it's 2' complement. For example: validRange(-4,3) would return 1, while validRange(5,3) would return 0 – Team. Coco Feb 06 '17 at 21:37
  • Shift the value to the right `while (value && ~value)`. In other words, if you keep shifting the value to the right, it will eventually be 0 (if it started as a positive number) or all 1's (if it started as a negative number). Then you'll need to add 1 to the bit count if is was a negative number. – user3386109 Feb 06 '17 at 21:45
  • I'm not allowed to use loops or conditional statements :/ – Team. Coco Feb 06 '17 at 21:46
  • Your shifts exhibit undefined behavior when `bits` is equal to the number of bits in an `int` (or greater). Of course, in that case, the function could trivially return 1. – John Bollinger Feb 06 '17 at 21:48
  • I think we are supposed to assume it is, at most, 32 bits – Team. Coco Feb 06 '17 at 21:50
  • @Team.Coco assuming that `bits` is at most 32 is not sufficient to avoid UB. You get UB if it is exactly 32, too (supposing that `int` is not larger than that). That's a case I would expect to work properly, myself. It might turn out to work for you regardless, but it cannot be relied upon to do so everywhere or everywhen. – John Bollinger Feb 06 '17 at 21:53
  • Are you permitted to use conditional statements? – John Bollinger Feb 06 '17 at 21:57
  • Nope. Just those operations listed and variables – Team. Coco Feb 06 '17 at 22:13
  • Well, you're using assignment operators (`=`) and `-` in your example code, and those are not on your list. It seems likely that at least the assignment operator is intended to be allowed, but the omission of `-` might be intentional. Anyway, that does lead me to ask you to confirm that the relational operators (`==`, `<`, etc.) are indeed forbidden. – John Bollinger Feb 06 '17 at 22:19
  • Yea, I just noticed that I have mistakenly used operators I wasn't supposed to. I will correct it. – Team. Coco Feb 06 '17 at 22:26

2 Answers2

2

Two's complement negative numbers always have a '1' in their high bit.

You can convert from negative to positive (and vice versa) by converting from FF -> 00 -> 01. That is, invert the bits, add 1. (01 -> FE -> FF also works: invert the bits, add 1)

A positive number can be represented if the highest set bit in the number is within your range. (nbits - 1: 7 bits for an 8 bit signed char, etc.)

I'm not sure if your constraints allow you to use arrays. They would speed up some things but can be replaced with loops or if statements.

Anyway, if 1 << (NUM_INT_BITS-1) is set on your input, then it's negative. Invert, add one.

Now, consider 0. Zero is a constant, and it's always the same no matter how many bits. But if you invert 0, you get "all the bits" which changes by architecture. So, ALL_BITS = ~0.

If you want to know if a positive number can be represented in 2 bits, check to see if any bits greater than or equal to bit 2 are set. Example:

two_bits = 0b00000011
any_other_bits = ~two_bits # Result: 0b11...11100
if positive_number & any_other_bits
    this number is too fat for these bits!

But how do you know what ~two_bits should be? Well, it's "all set bits except the bottom however-many". And you can construct that by starting with "all set bits" and shifting them upwards (aka, "left") however-many places:

any_other_bits = ~0 << 2  # where "2" is the number of bits to check

All together now:

if (val & ((unsigned)INT_MAX + 1))
    val = ~val + 1;

mask = ~0 << bits;
too_wide = val & mask;
return !too_wide;
aghast
  • 14,785
  • 3
  • 24
  • 56
  • From the comments: "I'm not allowed to use loops or conditional statements :/" – Andrew Cottrell Feb 06 '17 at 22:01
  • You must be very careful shifting values of signed type, for a left shift that otherwise would produce a value that is out of range for the type produces undefined behavior. Inasmuch as you seem to be depending on doing so, you're giving poor advice. One can work around this by working with an unsigned type; e.g. `0U << bits`, but you still have to be careful not to try to assign an out-of-range value to an `int` variable, too. – John Bollinger Feb 06 '17 at 22:02
1

To test if a number can be represented in a N-bit 2s compliment number: Simply test that either

  • The number bitwise-and'ed with the compliment of a word with the low (N-1) bits set is equal to zero
  • OR The high InputBitWidth-(N-1) bits of the number are 1s.

mask=(1<<(bits-1))-1; return ( !(val&mask) | !((val&~mask)^~mask) );

ggorlen
  • 44,755
  • 7
  • 76
  • 106
AShelly
  • 34,686
  • 15
  • 91
  • 152