shiftR
в Data.Bits выполняет арифметический сдвиг для Integers
. Есть ли стандартный способ правильно выполнить логический сдвиг?
Я могу придумать два способа сделать это. Возьмите частное на 2 ^ n:
unsignedShiftR i n = i `quot` (2 ^ n)
Другой способ - замаскировать верхние n бит после арифметического сдвига (хотя я не уверен, что вы можете получить позицию для маски).
2 ответа
По какой-то причине он не включен в Data.Bits
, но есть GHC primop: uncheckedIShiftRL#
. Кроме того, GHC.Base
экспортирует более безопасную версию как iShiftRL#
:
iShiftRL# :: Int# -> Int# -> Int#
a `iShiftRL#` b | isTrue# (b >=# WORD_SIZE_IN_BITS#) = 0#
| otherwise = a `uncheckedIShiftRL#` b
Мы можем обернуть либо версию GHC.Base
, либо примоп с различным количеством проверок:
{-# 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)
Похожие вопросы
Новые вопросы
haskell
Haskell — это чисто функциональный язык программирования со строгой статической типизацией, отложенными вычислениями, обширной поддержкой параллелизма и параллелизма, а также уникальными возможностями абстракции.