potrzebne do odczytu i zapisu liczb całkowitych w sposób, który jest zgodny z tym, co robi Java z jego BigInteger klasa:odczyt/zapis Haskell Integer w reprezentacji uzupełnienie dwójkowe
Zwraca tablicę bajtów zawierający reprezentację uzupełnienie do dwóch z ten BigInteger. Tablica bajtów będzie w kolejności bajtów big-endian: znaczący bajt znajduje się w elemencie zerowym. Tablica będzie zawierała minimalną liczbę bajtów wymaganych do reprezentowania tego BigInteger, , zawierającego co najmniej jeden bit znaku, który jest (ceil ((this.bitLength() + 1)/8)).
Niestety, to wyklucza, co oferuje Data.Binary
. Czy jest coś skutecznego do przeprowadzenia konwersji według tej konwencji gdzieś w bibliotekach? ByteString
< ->Jeśli nie, jak można to zrobić?
oparciu o odpowiedź od Thomas M. Dubuisson (i dalszej dyskusji) Obecnie mam
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
który jest bardziej gadatliwy niż to, co miałem nadzieję, nadal zdobywa funkcję bs2i
.
Czy musi być przenośny, czy można założyć GHC z pakietem 'integer-gmp'? –
Wolałbym przenośne rozwiązanie. Jeśli dobrze pamiętam, nawet GHC można zbudować bez GMP? To byłoby wtedy trochę zbyt kruche. – Waldheinz
Tak, można go zbudować za pomocą 'integer-simple'. Możesz po prostu być bardziej efektywny, jeśli używasz elementów wewnętrznych. Jeszcze jedno pytanie, czy chcesz 'ByteString' zawierający tylko bity liczby, czy też jest częścią większego' ByteString', abyś miał pole określające liczbę bajtów składających się na reprezentację? –