Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Java's BigInteger sign-magnitude works

Consider the following code:

int i = 1;
System.out.println("1 binary: " + Long.toBinaryString(i));
long ri = Long.reverse(i);
System.out.println("1 reverse bit decimal: " + ri);
System.out.println("1 reverse bit binary: "+ Long.toBinaryString(ri));
BigInteger bil = new BigInteger(1, Longs.toByteArray(ri));
System.out.println("1 Sign-Magnitude BigInteger toString: " + bil.toString());

The output is:

1 binary: 1
1 reverse bit decimal: -9223372036854775808
1 reverse bit binary: 1000000000000000000000000000000000000000000000000000000000000000
1 Sign-Magnitude BigInteger toString: 9223372036854775808

Can anyone help to explain why the value of "1 Sign-Magnitude BigInteger toString:" is 9223372036854775808 (2^63)?

like image 263
Terminal User Avatar asked Nov 02 '25 10:11

Terminal User


1 Answers

To get the sign-magnitude of a value, you simply take its absolute value as magnitude and remember the sign in a separate bit (or byte).

The sign-magnitude representation of, say, 722 is simply:

sign = 0
magnitude = 722

The sign magnitude of -722 is simply:

sign = 1
magnitude = 722

That is also what BigInteger uses.

Your code reverses a value, which means that, say, the 8 bit value 00000001 (1) is changed into 10000000 (128 or 2^7). That is not the same as inverting, which turns e.g. 00000001 (1) into 11111110 (254). That is what one's complement does. The generally used two's complement negates 00000001 (1) into 11111111 (255, i.e. 256 - 1). You should read up about two's complement, which takes some understanding. Sign-magnitude is, however, very easy to understand (but not always very practical -- addition, subtraction are different for signed and unsigned, etc. -- and that is why most processors use two's-complement)

So again: sign-magnitude works like this:

sign = (n < 0)
magnitude = abs(n)
like image 77
Rudy Velthuis Avatar answered Nov 04 '25 20:11

Rudy Velthuis