I need to read and write integers in a way that is compatible with what the Java BigInteger class does with it :
Returns an array of bytes containing a two-component representation of this BigInteger. The byte array will be in byte byte order: the most significant byte is in the null element. The array will contain the minimum number of bytes required to represent this BigInteger, including at least one signed bit, which is equal to (ceil ((this.bitLength () + 1) / 8)).
Unfortunately, this excludes what it offers Data.Binary. Is there something effective to convert ByteString↔ Integerafter this convention somewhere in the libraries? If not, how can this be done?
Based on the answer of Thomas M. Dubuison (and the subsequent discussion), I am currently
i2bs :: Integer -> B.ByteString
i2bs x
| x == 0 = B.singleton 0
| x < 0 = i2bs $ 2 ^ (8 * bytes) + x
| otherwise = B.reverse $ B.unfoldr go x
where
bytes = (integerLogBase 2 (abs x) + 1) `quot` 8 + 1
go i = if i == 0 then Nothing
else Just (fromIntegral i, i `shiftR` 8)
integerLogBase :: Integer -> Integer -> Int
integerLogBase b i =
if i < b then
0
else
-- Try squaring the base first to cut down the number of divisions.
let l = 2 * integerLogBase (b*b) i
doDiv :: Integer -> Int -> Int
doDiv i l = if i < b then l else doDiv (i `div` b) (l+1)
in doDiv (i `div` (b^l)) l
In more detail than I had hoped, the function is still lacking bs2i.
source
share