1

I have a 3 byte signed number that I need to determine the value of in Java. I believe it is signed with one's complement but I'm not 100% sure (I haven't studied this stuff in more than 10 years and the documentation of my problem isn't super clear). I think the problem I'm having is Java does everything in two's complement. I have a specific example to show:

  • The original 3-byte number: 0xEE1B17

  • Parsed as an integer (Integer.parseInt(s, 16)) this becomes: 15604503

  • If I do a simple bit flip (~) of this I get (I think) a two's complement representation: -15604504

  • But the value I should be getting is: -1172713

What I think is happening is I'm getting the two's complement of the entire int and not just the 3 bytes of the int, but I don't know how to fix this.

What I have been able to do is convert the integer to a binary string (Integer.toBinaryString()) and then manually "flip" all of the 0s to 1s and vice-versa. When then parsing this integer (Integer.parseInt(s, 16)) I get 1172712 which is very close. In all of the other examples I need to always add 1 to the result to get the answer.

Can anyone diagnose what type of signed number encoding is being used here and if there is a solution other than manually flipping every character of a string? I feel like there must be a much more elegant way to do this.

EDIT: All of the responders have helped in different ways, but my general question was how to flip a 3-byte number and @louis-wasserman answered this and answered first so I'm marking him as the solution. Thanks to everyone for the help!

rjcarr
  • 2,072
  • 2
  • 22
  • 35

3 Answers3

2

If you want to flip the low three bytes of a Java int, then you just do ^ 0x00FFFFFF.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Yes, thanks, I knew it would be simple. Your answer is what I was looking for so I'll mark it as the solution, but any idea why I have to add a 1 to that number to get the desired result? – rjcarr Feb 04 '13 at 20:05
  • In two's complement, `~x == -x - 1`. So that's probably an artifact of the one's complement stuff. – Louis Wasserman Feb 04 '13 at 20:07
1

0xFFEE1B17 is -1172713 You must only add the leading byte. FF if the highest bit of the 3-byte value is set and 00 otherwise.

A method which converts your 3-byte value to a proper intcould look like this:

if(byte3val>7FFFFF)
  return byte3val| 0xFF000000;
else 
  return byte3val;
MrSmith42
  • 9,961
  • 6
  • 38
  • 49
  • Thanks for the quick response ... when you say "0xFFEE1B17 is -1172713" in what number's complement do you mean? – rjcarr Feb 04 '13 at 20:08
  • @rjcarr: the in nearly all systems (and also by java) used [2-compliment](http://en.wikipedia.org/wiki/Two's_complement) – MrSmith42 Feb 04 '13 at 20:10
0

Negative signed numbers are defined so that a + (-a) = 0. So it means that all bits are flipped and then 1 added. See Two's complement. You can check that the condition is satisfied by this process by thinking what happens when you add a + ~a + 1.

You can recognize that a number is negative by its most significant bit. So if you need to convert a signed 3-byte number into a 4-byte number, you can do it by checking the bit and if it's set, set also the bits of the fourth byte:

if ((a & 0x800000) != 0)
    a = a | 0xff000000;

You can do it also in a single expression, which will most likely perform better, because there is no branching in the computation (branching doesn't play well with pipelining in current CPUs):

a = (0xfffffe << a) >> a;

Here << and >> perform byte shifts. First we shift the number 8 bits to the right (so now it occupies the 3 "upper" bytes instead of the 3 "lower" ones), and then shift it back. The trick is that >> is so-called Arithmetic shift also known as signed shift. copies the most significant bit to all bits that are made vacant by the operation. This is exactly to keep the sign of the number. Indeed:

(0x1ffffe << 8) >> 8        ->  2097150
(0xfffffe << 8) >> 8        ->  -2

Just note that java also has a unsigned right shift operator >>>. For more information, see Java Tutorial: Bitwise and Bit Shift Operators.

Petr
  • 62,528
  • 13
  • 153
  • 317
  • @MrSmith42 Thanks for pointing that out, I've corrected it. Of course it should be bitwise and/or. – Petr Feb 04 '13 at 20:22