简体   繁体   中英

Java negative BigInteger toString

It seems I have a two's complement issue with Java's BigInteger. I have a 64-bit integer where only the msb and the second msb are set to 1, the rest is 0.

In decimal this comes up to: -4611686018427387904

The Java side of my application receives this decimal number as a string, and converts it to BigInteger like so:

BigInteger bi = new BigInteger("-4611686018427387904", 10);

Then, it needs to display this number both in binary and hex forms. I tried to use:

String bin = bi.toString(2);
String hex = bi.toString(16);

but I'm getting:

-100000000000000000000000000000000000000000000000000000000000000

-4000000000000000

whereas I expect to get:

1100000000000000000000000000000000000000000000000000000000000000

c000000000000000

Any tips?

Number always fits in 64 bits:

If your number always fits in 64 bits you can put it in a long and then print the bits / hex digits.

long l = bi.longValue();
String bin = Long.toBinaryString(l);
String hex = Long.toHexString(l);

System.out.println(bin);
System.out.println(hex);

Number may not always fit in 64 bits:

If the number does not always fit in 64 bits, you'll have to solve it "manually". To convert a number to it's two's complement representation you do the following:

  • If number is positive, do nothing
  • If number is negative:
    • Convert it to its absolute value
    • Complement the bits
    • Add 1

For a BigInteger the conversion looks as follows:

if (bi.compareTo(BigInteger.ZERO) < 0)
    bi = bi.abs().not().add(BigInteger.ONE);

If you print it using bi.toString(2) you'll still get the sign character, instead of a leading 1 . This can be solved by simply appending .replace('-', '1') to the string.

There is a BigInteger.toByteArray() method, that returns two's complement representation of BigInteger as a byte[] . All you need is to print that array in hex or binary form:

byte[] bs = bi.toByteArray();
for (byte b: bs) {
     System.out.print(String.format("%02X", 0xff & b));
}

The binary number 1100000000000000000000000000000000000000000000000000000000000000 is definitely a positive number, right. It's equal to 2^63 + 2^62. I don't see why you'd expect a negative number to become positive when you convert to base 2 or base 16.

You are confusing the base n representation with the internal representation of numbers.

If the number is 64 bits or less, then the simple way to solve this is to convert to a long and then use Long.toHexString() .

what you mean? Do you want to get Two's complement?

if you mean that, maybe i can give you an example

import java.util.*;
public class TestBina{
static void printBinaryInt(int i){
System.out.println("int:"+i+",binary:");
System.out.print("  ");
for(int j=31;j>=0;j--)
   if(((1<<j)&i)!=0)
    System.out.print("1");
   else
    System.out.print("0");
  System.out.println();
 }
 public static void main(String [] args){
  Random rand = new Random();
  int i = rand.nextInt();
  int j = rand.nextInt();
  printBinaryInt(i);
  printBinaryInt(j);
  printBinaryInt(10);
  printBinaryInt(-10);
 }
}  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM