Go & Javascript seems to be doing the same thing on BigInt: toBytes returns the absolute value with the sign seperately. While Java returns the Two’s complement representation. It makes it just a bit trickier to get the right binary representation.

This post explores ways to implement the Two’s complement representation in javascript & Go

javascript Link to heading

$ node
> BigInt(-257).toString(16)
'-101'
> BigInt(257).toString(16)
'101'
>

It’s basically the sign plus the hex of the absolute value

Go Link to heading

package main

import (
	"fmt"
	"math/big"
)

func main() {
	fmt.Printf("%#v", big.NewInt(-257).Bytes())
}

// output
// []byte{0x1, 0x1}

From big.Int.Bytes() documentation:

Bytes returns the absolute value of x as a big-endian byte slice.

java / kotlin Link to heading

println(Arrays.toString(BigDecimal("-257").unscaledValue().toByteArray()))

// output
// [-2, -1]

The doc of unscaledValue says:

Returns a byte array containing the two's-complement representation of this
BigInteger. The byte array will be in big-endian byte-order: the most
significant byte is in the zeroth element. The array will contain the minimum
number of bytes required to represent this BigInteger, including at least one
sign bit, which is (ceil((this.bitLength() + 1)/8)). (This representation is
compatible with the (byte[]) constructor.)