У меня есть строка "1001", и мне нужна строка "9".
В числовой библиотеке есть (довольно неуклюжая) showIntAtBase, но мне не удалось найти обратное.
У меня есть строка "1001", и мне нужна строка "9".
В числовой библиотеке есть (довольно неуклюжая) showIntAtBase, но мне не удалось найти обратное.
Вот более или менее то, что вы искали от Prelude. Из Numeric:
(NB: readInt является "двойным" из showIntAtBase, а readDec является "двойным" из showInt. Непоследовательное именование - это исторический случай.)
import Data.Char (digitToInt)
import Data.Maybe (listToMaybe)
import Numeric (readInt)
readBin :: Integral a => String -> Maybe a
readBin = fmap fst . listToMaybe . readInt 2 (`elem` "01") digitToInt
-- readBin "1001" == Just 9
Прошло некоторое время с момента публикации, но для будущих читателей я бы использовал следующее:
import Data.Char (digitToInt)
import Data.List (foldl')
toDec :: String -> Int
toDec = foldl' (\acc x -> acc * 2 + digitToInt x) 0
Не нужно замедлять работу, используя ^
, reverse
, zipWith
, length
и т.д.
Кроме того, использование строгой фальшивки снижает требования к памяти.
Из PLEAC:
bin2dec :: String -> Integer
bin2dec = foldr (\c s -> s * 2 + c) 0 . reverse . map c2i
where c2i c = if c == '0' then 0 else 1
Это помогает? http://pleac.sourceforge.net/pleac_haskell/numbers.html
со страницы:
bin2dec :: String -> Integer
bin2dec = foldr (\c s -> s * 2 + c) 0 . reverse . map c2i
where c2i c = if c == '0' then 0 else 1
-- bin2dec "0110110" == 54
Поскольку
1001 = 1 * 2^0 + 0 * 2^1 + 0 * 2^2 + 1 * 2^3 = 1 + 0 + 0 + 8 = 9
┌───┬───┬───┬───┐
│1 │0 │0 │1 │
├───┼───┼───┼───┤
│2^3│2^2│2^1│2^0│
└───┴───┴───┴───┘
так очевидно:
fromBinary :: String -> Int
fromBinary str = sum $ zipWith toDec (reverse str) [0 .. length str]
where toDec a b = digitToInt a * (2 ^ b)
binario :: Int -> [Int]
binario 1 = [1]
binario n = binario(div x 2)++(mod n 2:[])
кредиты @laionzera