3

I'm working on a function that returns 1 when x can be represented as an n-bit, 2’s complement number and 0 if it can't. Right now my code works for some examples like (5, 3), (-4, 3). But I can't get it to work for instances where n is bigger than x like (2, 6). Any suggestions as to why?

I do have restrictions though which include casting, either explicit or implicit, relative comparison operators (<, >, <=, and >=), division, modulus, and multiplication, subtraction, conditionals (if or ? :), loops, switch statements, function calls, and macro invocations. Assume 1 < n < 32.

int problem2(int x, int n){

    int temp = x;
    uint32_t mask;
    int maskco;

    mask = 0xFFFFFFFF << n;
    maskco = (mask | temp);

    return (maskco) == x;

}
phuclv
  • 37,963
  • 15
  • 156
  • 475
Rbutler93
  • 73
  • 1
  • 11

2 Answers2

2
int problem2_mj(int x, int n){
    unsigned int r;
    int const mask = (-x) >> sizeof(int) * CHAR_BIT - 1;

    r = (-x + mask - (1 & mask)) ^ mask;  // Converts +n -> n, -n -> (n-1)
    return !(((1 << (n-1)) - r) >> sizeof(int) * CHAR_BIT - 1);
}
  1. Find the absolute value and subtract 1 if the number was negative
  2. Check if number is less than or equal to 2n-1

Check a working demo here


As per your updated request here is the code how to add two numbers:

int AddNums(int x, int y)
{
  int carry;

  // Iteration 1
  carry = x & y;  
  x = x ^ y; 
  y = carry << 1;

  // Iteration 2
  carry = x & y;  
  x = x ^ y; 
  y = carry << 1;

  ...

  // Iteration 31 (I am assuming the size of int is 32 bits)
  carry = x & y;  
  x = x ^ y; 
  y = carry << 1;

  return x;
}
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • Thank you, it makes sense but I can't use subtraction. Is there a way to do it without subtraction. – Rbutler93 Jan 30 '15 at 07:40
  • Yes, write an auxiliary function to perform subtraction using `^` and `&` – Mohit Jain Jan 30 '15 at 07:41
  • I'm a bit confused on to how that would work could you explain it to me? – Rbutler93 Jan 30 '15 at 07:50
  • Which part, 1 or 2 or both? – Mohit Jain Jan 30 '15 at 07:59
  • Both, I understand what each operator does but I am confused as to how you would use it to subtract. – Rbutler93 Jan 30 '15 at 08:03
  • `a - b` is same as `a + (-b)`. You can use `a ^ b` to do addition without carry and `a & b` to get carry. I guess this hint is good enough to keep you moving. – Mohit Jain Jan 30 '15 at 08:17
  • in your question you said that "Division, modulus, and multiplication, subtraction" is allowed – phuclv Jan 30 '15 at 11:21
  • They are restrictions everything in that paragraph is a restriction. – Rbutler93 Jan 30 '15 at 11:24
  • 1
    Actually your paragraph is broken. Each new sentence has no verb and object. Why use a period when the old sentence hasn't finished? And if you know what 2's complement is then why can't you construct a subtraction from addition? – phuclv Jan 30 '15 at 11:26
  • You know I hadn't noticed I copied and pasted that part. I can't seem to visualize it. I'm still having trouble even after it was explained. – Rbutler93 Jan 30 '15 at 11:33
  • @MohitJain So, based on your example this would be equivalent to what you wrote? temp = -x + mask; temp2 = (-1 & mask); carry = temp & temp2; temp = temp ^ temp2; temp2 = carry << temp; r = temp ^ mask; – Rbutler93 Jan 30 '15 at 12:03
  • 1
    then please fix the question to make it clearer. @MohitJain why don't just use `-y = ~y + 1`? There's no need to write an adder in this case – phuclv Jan 30 '15 at 12:08
2

In your function, temp is just redundant, and maskco always have the top bit(s) set, so it won't work if x is a positive number where the top bit isn't set

The simple solution is to mask out the most significant bits of the absolute value, leaving only the low n bits and check if it's still equal to the original value. The absolute value can be calculated using this method

int fit_in_n_bits(int x, int n)
{
    int maskabs = x >> (sizeof(int) * CHAR_BIT - 1);
    int xabs    = (x + maskabs) ^ maskabs;  // xabs = |x|
    int nm      = ~n + 1U;                  // nm = -n
    int mask    = 0xFFFFFFFFU >> (32 + nm);
    return (xabs & mask) == xabs;
}

Another way:

int fit_in_n_bits2(int x, int n)
{
    int nm       = ~n + 1U;
    int shift    = 32U + nm;
    int masksign = x >> (shift + 1);
    int maskzero = 0xFFFFFFFFU >> shift;
    return ((x & maskzero) | masksign) == x;
}

You can also check out oon's way here

int check_bits_fit_in_2s_complement(signed int x, unsigned int n) {
  int mask = x >> 31;

  return !(((~x & mask) + (x & ~mask))>> (n + ~0));
}

One more way

/* 
 * fitsBits - return 1 if x can be represented as an 
 *  n-bit, two's complement integer.
 *   1 <= n <= 32
 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int fitsBits(int x, int n) {
    int r, c;
    c = 33 + ~n;
    r = !(((x << c)>>c)^x);
    return r;
}

Related:

phuclv
  • 37,963
  • 15
  • 156
  • 475