簡體   English   中英

將Int或Integer轉換為[Word8]或[Bit]

[英]Convert Int or Integer to [Word8] or [Bit]

有沒有一種有效的方法將Int (最好是Integer )轉換為Word8列表甚至是位列表? {G,H}為Int -> [Word8]沒有產生任何有希望的結果......

IntInteger都是Bits類型類的實例,因此您可以使用該類的函數隨意提取單個位。

由於Int也是Storable的實例,因此您可以使用sizeOf獲取其大小。 因此,對Int和其他類型的BitsStorable實例的(低效)實現是:

import Foreign.Storable
import Data.Bits

bitList :: (Storable a, Bits a) => a -> [Bool]
bitList x = map (testBit x) [0..8*(sizeOf x)-1]

這給出了例如

bitList (0 :: Int) == [False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False,False]
bitList (-1 :: Int) == [True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]
bitList (16 :: Word8) == [False,False,False,False,True,False,False,False]
bitList (maxBound ::Word32) == [True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True,True]

以下是適用於從谷物包裝內臟撕下的Integer功能:

--
-- Fold and unfold an Integer to and from a list of its bytes
--
unroll :: Integer -> [Word8]
unroll = unfoldr step
  where
    step 0 = Nothing
    step i = Just (fromIntegral i, i `shiftR` 8)

roll :: [Word8] -> Integer
roll   = foldr unstep 0
  where
    unstep b a = a `shiftL` 8 .|. fromIntegral b

@gspr建議的另一種方法,但不需要Storable (它支持Integer s作為獎勵!):

import Data.Bits

bitList :: Bits a => a -> [Bool]
bitList x =
    [ testBit x i
    | i <- maybe [0..] (enumFromTo 0 . subtract 1) (bitSizeMaybe x)
    ]

它正確地猜測了整數和單詞的大小,但要注意它會為Integer提供無限數量的位。

我通過轉換它來擴展@ max-taldykin以顯示從右到左的位,類似於通常顯示位的方式。

import Data.Bits (FiniteBits, finiteBitSize, testBit)
import Data.Int (Int32)

bitList :: FiniteBits a => a -> [Bool]
bitList x = let size = finiteBitSize x
            in [testBit x i | i <- enumFromThenTo size (size - 1) 0]

bitListToNum :: Num b => [Bool] -> [b]
bitListToNum = map (\b -> case b of { True -> 1; False -> 0 })

main = do 
    let listOfBits = bitList (65 :: Int32)
    print $ bitListToNum listOfBits

還提供了將其轉換為數字的功能。

在此更新: https//gist.github.com/a7f3ba5976accc113736f3b22929dddc

您可以使用Data.Vector.StorableunsafeCast將其轉換為另一種int類型,然后通過索引將它們拉出來。

let w32 = 800 :: Int32
    vec = singleton w32
    vec' = unsafeCase vec :: Vector Word8
in toList vec'

或類似於Ptr和東西的東西。

注意:因為它表明這是一個不安全的操作,所以盡可能多地驗證數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM