5

In Java, I can get a BigInteger from a String like this:

public static void main(String[] args) {
    String input = "banana";
    byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
    BigInteger bigInteger = new BigInteger(bytes);
    System.out.println("bytes:      " + Arrays.toString(bytes));
    System.out.println("bigInteger: " + bigInteger);
}

Which will print

bytes:      [98, 97, 110, 97, 110, 97]
bigInteger: 108170603228769

I'm trying to get the same result in JavaScript using the big-integer library. But as you can see this code returns a different value:

var bigInt = require('big-integer');

function s(x) {
    return x.charCodeAt(0);
}

var bytes = "banana".split('').map(s);
var bigInteger = bigInt.fromArray(bytes);
console.log("bytes:      " + bytes);
console.log("bigInteger: " + bigInteger);

output:

bytes:      98,97,110,97,110,97
bigInteger: 10890897

Is there a way to get the result I'm getting in Java with JavaScript? And would that be possible also if the array has a length of 32?

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • 1
    @rottenoats big-integer *is* a Javascript library. This *is* a Javascript question. – CertainPerformance Oct 03 '18 at 08:32
  • 1
    Can you explain how `[98, 97, 110, 97, 110, 97]` gets transformed to `108170603228769`? I'm afraid I don't see the pattern. A more minimal example, like an array with two or three elements, might be informative – CertainPerformance Oct 03 '18 at 08:33
  • 3
    The doc page you linked says `fromArray` defaults base to 10. Given this byte array has the top bit of the first byte clear, [the Java BigInteger ctor is using effectively base 256 bigendian](https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#BigInteger-byte:A-) **Use base 256.** – dave_thompson_085 Oct 03 '18 at 08:49
  • @CertainPerformance: try a hex output for the bytes and for the BigInteger. Then you will see where the individual bytes go. Hex output will need exactly two hex digits per byte. – Rudy Velthuis Oct 03 '18 at 14:43
  • @CertainPerformance: The bytes are, in hex: `[62,61,6E,61,6E,61]`. The hex reprentation of the BigInteger with value `108170603228769` is `62616E616E61`. I guess it is clear now how these values get transformed to the BigInteger. It is not obvious from the decimal representations, but in hex it is. – Rudy Velthuis Oct 03 '18 at 15:50

1 Answers1

1

BigInteger(byte[]) takes the two's-complement binary representation while bigInt.fromArray() takes an array of digits with a default base of 10.

As dave_thompson_085 said, you can use base 256:

var bigInteger = bigInt.fromArray(bytes, 256);
console.log("bigInteger: " + bigInteger); // 108170603228769
Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • I'm getting the following error when running this: `/Users/sietzevliegen/node_modules/big-integer/BigInteger.js:1122` `val = val.add(digits[i].times(pow));` `TypeError: digits[i].times is not a function` – sietzevliegen Oct 03 '18 at 11:20
  • It works with `http://peterolson.github.com/BigInteger.js/BigInteger.min.js`, not sure why it fails for you. – Karol Dowbecki Oct 03 '18 at 11:22
  • It works actually. The variable I was passing was incorrect, that's how I messed it up. Using the snippet from the original question solved that problem – sietzevliegen Oct 03 '18 at 11:34