3

My numbers are base 256 from left to right and represented in byte array. I would like to convert them to BigInteger such that below examples will work:

  • [5] -> 5
  • [200] -> 200
  • [0,1] -> 256
  • [100,2] -> 612

I came up with this solution:

    byte[] input = new byte[]{(byte) 200,2};
    BigInteger a = BigInteger.ZERO;
    BigInteger base = BigInteger.valueOf(256);
    for (int i = 0; i < input.length; i++) {
        a = a.add(BigInteger.valueOf(input[i] & 0xFF).multiply(base.pow(i)));
    }
    System.out.println(a);

While it works, it feels very inefficient. Is there a more efficient way of doing this?

5
  • If this code works fine, then this question is off topic on Stack Overflow, but may be good for our sister site Code Review. Commented Jan 21, 2018 at 21:44
  • @JoeC I want to find a more efficient way of doing this. Creating multiple BigIntegers is not the best you can do.... Commented Jan 21, 2018 at 21:45
  • @ThomasFritsch I got a different byte order, my examples will not convert that way Commented Jan 21, 2018 at 21:54
  • @Ilya_Gazman But you could just reverse the byte order in the array and then use new BigInteger(array). That'd be much most efficient than what you're currently doing. Commented Jan 21, 2018 at 21:55
  • @Andreas it sounds more efficient then my solution, but it didn't worked for me. Can you make my examples work with that idea? Commented Jan 21, 2018 at 21:56

2 Answers 2

9

Easiest way to create a BigInteger from a byte array is to use the new BigInteger​(byte[] val) constructor:

Translates a byte array containing the two's-complement binary representation of a BigInteger into a BigInteger. The input array is assumed to be in big-endian byte-order: the most significant byte is in the zeroth element.

Since your input array is in little-endian order, and you don't want negative numbers returned, you need to reverse the bytes and ensure the first byte is 0-127, so the sign bit is not set. Easiest way to do that is to make the first byte 0.

Example: [2, 20, 200] -> [0, 200, 20, 2]

Here is the code for that:

private static BigInteger toBigInt(byte[] arr) {
    byte[] rev = new byte[arr.length + 1];
    for (int i = 0, j = arr.length; j > 0; i++, j--)
        rev[j] = arr[i];
    return new BigInteger(rev);
}

Test

byte[][] data = { {5},
                  {(byte)200},
                  {0,1},
                  {100,2} };
for (byte[] arr : data)
    System.out.println(toBigInt(arr));

Output

5
200
256
612
Sign up to request clarification or add additional context in comments.

Comments

2

i know you can do this :

import java.math.BigInteger;
import java.util.BitSet;

public class Main {
    public static void main(String[] argv) throws Exception {
        // A negative value
        byte[] bytes = new byte[] { (byte) 0xFF, 0x00, 0x00 }; // -65536
        // A positive value
        bytes = new byte[] { 0x1, 0x00, 0x00 }; // 65536
        BitSet set = BitSet.valueOf(bytes);
        set.flip(0, set.length());
        byte[] flipped = set.toByteArray();

        BigInteger bi = new BigInteger(flipped);
    }
}

I use BitSet for swat bit cause you want left to rigth but BigInteger constructor use rigth to left

2 Comments

Byte order is reversed from what's in the question.
sorry i dont see , i have fix that

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.