2

The method takes in an n-bit 2's complement number whose absolute value we're trying to find, and the number of bits that the number will be. Here are some examples:

abs(0x00001234, 16); // => 0x00001234

abs(0x00001234, 13); // => 0x00000DCC

So you can see that in the first example that 0x00001234 just yields itself because with 16 bits it has enough leading zeroes to just be itself.

However, for the second example, using 13 bits makes 0x00001234 have a 1 in the sign bit, so when you convert this 13-bit number to a positive number, it yields 0x00000DCC.

I feel like what I have so far should work, but it isn't working for some cases :/ Any idea what's wrong or what direction I should be going in?

EDIT: Also forgot to mention, we can't use >>>, or +,-,*,/ unless we're just incrementing by 1.

public static int abs(int num, int n)
{

    boolean set = ((1 << n-1) & num) == (1 << n-1);
    if (!set) {
        return num;
    } else {
        int bitmask = (0x7FFFFFFF >> (32-n)) | (1 << n-1);
        return (num ^ bitmask) + 1;
    }
}
Evan LaHurd
  • 977
  • 2
  • 14
  • 27

2 Answers2

2

wha, here you go for people who come by later:

  public static int abs(int num, int n)
  {
      int topbit = 1<<(n-1);
      int ones = (topbit<<1)-1;
      num &= ones;                     // sanity check
      if (0==(topbit&num)) {
          return num;
      } else {
          return (num ^ ones) + 1;
      }
  }

so the question is, can operations be removed from here to make this function faster?

thang
  • 3,466
  • 1
  • 19
  • 31
0

this is wrong

int bitmask = 0xFFFFFFFF >> (32 - n);

it will always be 0xFFFFFFFF, use

int bitmask = 0xFFFFFFFF >>> (32 - n);

see http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.19

UPDATE as I understood from your comment you are not allowed to use unsigned shift. In this case try

    int bitmask = (int) (0xFFFFFFFFL >> (32 - n));

full code

public static int abs(int num, int n) {
    int bitmask = (int) (0xFFFFFFFFL >> (32 - n));
    boolean set = ((1 << n - 1) & num) != 0;
    if (!set) {
        return num & bitmask;
    } else {
        return -(num | ~bitmask);
    }
}
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • that works, but we're actually not allowed to use it...sorry I didn't mention that before. Any way around this? – Evan LaHurd Jan 20 '13 at 06:14
  • 1
    yeah, use (0x7FFFFFFF >> (32-n)) |(1 << n-1). also observe that 1< – thang Jan 20 '13 at 06:21
  • that works too, but i still don't know how to work around 32- n since we can't use subtraction :/ – Evan LaHurd Jan 20 '13 at 06:24
  • should check, but i think (0x7FFFFFFF >> (32-n)) |(1 << n-1) is the same as (1< – thang Jan 20 '13 at 06:26
  • you can only add or subtract by 1, so n-1 is okay. – Evan LaHurd Jan 20 '13 at 06:27
  • 1
    he can't use / :p it's like trying to eat dinner blind folded. – thang Jan 20 '13 at 06:32
  • yeah, it works for all of the test cases, but I'm noticing that the way im using my boolean set variable won't work in all cases. For example, what if it was abs(0x00001234, 12)? It would see that the bit at 12 is 0, and return 0x00001234 when it should return the number to the right of the 0, which is 0x00000234, I believe. – Evan LaHurd Jan 20 '13 at 06:41
  • note that 0x00001234 is not a legit input for a 12 bit number because the 13th bit is set. what you can do to weed out problems like this is just by putting num &= ((1< – thang Jan 20 '13 at 06:50
  • it seems you have to return in case 1 (bitmask & num) – Evgeniy Dorofeev Jan 20 '13 at 07:09
  • and you can test the highest bit as boolean set = ((1 << n - 1) & num) != 0; – Evgeniy Dorofeev Jan 20 '13 at 07:13