【发布时间】:2023-03-29 03:35:01
【问题描述】:
我有字符串“1001”,我想要字符串“9”。
数值库有(相当笨重的)showIntAtBase,但我找不到相反的。
【问题讨论】:
-
这些函数都不能转换为十进制。它们从表示以 2 为基数的数字的字符串转换为机器的本机整数格式,除非您使用一些奇特的硬件,否则它肯定是打包的二进制表示。将 show 函数应用于整数时,会生成一个表示以 10 为底的数字的字符串。
标签: haskell
我有字符串“1001”,我想要字符串“9”。
数值库有(相当笨重的)showIntAtBase,但我找不到相反的。
【问题讨论】:
标签: haskell
来自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
【讨论】:
foldl'
foldr 和reverse 比foldl' 更可取。事实上,我在这里只能看到使用foldr 和reverse 的缺点。
这或多或少是您从 Prelude 中寻找的内容。 来自Numeric:
(注意: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
【讨论】:
digitToInt = subtract (fromEnum '0') . fromEnum,它适用于所有十进制数字(digitToInt 的内置实现也可以处理十六进制数字)。
因为
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)
【讨论】:
距离最初的帖子已经有一段时间了,但为了未来读者的利益,我会使用以下内容:
import Data.Char (digitToInt)
import Data.List (foldl')
toDec :: String -> Int
toDec = foldl' (\acc x -> acc * 2 + digitToInt x) 0
无需使用^、reverse、zipWith、length 等来减慢速度。
此外,使用严格折叠可以减少内存需求。
【讨论】:
binario :: Int -> [Int]
binario 1 = [1]
binario n = binario(div x 2)++(mod n 2:[])
感谢@laionzera
【讨论】:
import Control.Monad
import Data.Bits (shift)
-- Dirty version
binToInt :: String -> Int
binToInt = foldl' step 0
where
step acc '1' = shift acc 1 + 1
step acc _ = shift acc 1
-- Maybe version
mayBinToInt :: String -> Maybe Int
mayBinToInt = foldM step 0
where
step acc '0' = pure $ shift acc 1
step acc '1' = pure $ shift acc 1 + 1
step acc _ = Nothing
(当然,您可能还想在第二个字符串中以空字符串返回 Nothing。)
【讨论】: