如何对 Haskell 中的整数进行 unsigned/logical 右移?
How do you do an unsigned/logical shift right on an Integer in Haskell?
shiftR
in Data.Bits 对 Integers
进行算术移位。有没有一种标准的方法来正确地进行逻辑移位?
我可以想出两种方法来做到这一点。取商乘以 2^n:
unsignedShiftR i n = i `quot` (2 ^ n)
另一种方法是在算术移位后屏蔽高位 n 位(尽管我不确定您是否可以获得屏蔽的位置)。
出于某种原因,它未包含在 Data.Bits
中,但有一个 GHC primop: uncheckedIShiftRL#
. Also, GHC.Base
导出更安全的版本,如 iShiftRL#
:
iShiftRL# :: Int# -> Int# -> Int#
a `iShiftRL#` b | isTrue# (b >=# WORD_SIZE_IN_BITS#) = 0#
| otherwise = a `uncheckedIShiftRL#` b
我们可以用不同数量的检查包装 GHC.Base
版本或 primop:
{-# LANGUAGE MagicHash #-}
import GHC.Base
import GHC.Prim
uncheckedIShiftRL :: Int -> Int -> Int
uncheckedIShiftRL (I# n) (I# i) = I# (uncheckedIShiftRL# n i)
unsafeIShiftRL :: Int -> Int -> Int
unsafeIShiftRL (I# n) (I# i) = I# (iShiftRL# n i)
iShiftRL :: Int -> Int -> Int
iShiftRL (I# n) (I# i)
| isTrue# (i >=# 0#) = I# (iShiftRL# n i)
| otherwise = error "shift by negative amount"
就 Int
而言,标准的做法是将其转换为无符号类型并将其移动到那里:
import Data.Word
ushiftR :: Int -> Int -> Int
ushiftR n k = fromIntegral (fromIntegral n `shiftR` k :: Word)
shiftR
in Data.Bits 对 Integers
进行算术移位。有没有一种标准的方法来正确地进行逻辑移位?
我可以想出两种方法来做到这一点。取商乘以 2^n:
unsignedShiftR i n = i `quot` (2 ^ n)
另一种方法是在算术移位后屏蔽高位 n 位(尽管我不确定您是否可以获得屏蔽的位置)。
出于某种原因,它未包含在 Data.Bits
中,但有一个 GHC primop: uncheckedIShiftRL#
. Also, GHC.Base
导出更安全的版本,如 iShiftRL#
:
iShiftRL# :: Int# -> Int# -> Int#
a `iShiftRL#` b | isTrue# (b >=# WORD_SIZE_IN_BITS#) = 0#
| otherwise = a `uncheckedIShiftRL#` b
我们可以用不同数量的检查包装 GHC.Base
版本或 primop:
{-# LANGUAGE MagicHash #-}
import GHC.Base
import GHC.Prim
uncheckedIShiftRL :: Int -> Int -> Int
uncheckedIShiftRL (I# n) (I# i) = I# (uncheckedIShiftRL# n i)
unsafeIShiftRL :: Int -> Int -> Int
unsafeIShiftRL (I# n) (I# i) = I# (iShiftRL# n i)
iShiftRL :: Int -> Int -> Int
iShiftRL (I# n) (I# i)
| isTrue# (i >=# 0#) = I# (iShiftRL# n i)
| otherwise = error "shift by negative amount"
就 Int
而言,标准的做法是将其转换为无符号类型并将其移动到那里:
import Data.Word
ushiftR :: Int -> Int -> Int
ushiftR n k = fromIntegral (fromIntegral n `shiftR` k :: Word)