【问题标题】:Convert a string representing a binary number to a base 10 string haskell将表示二进制数的字符串转换为以 10 为底的字符串 haskell
【发布时间】:2023-03-29 03:35:01
【问题描述】:

我有字符串“1001”,我想要字符串“9”。

数值库有(相当笨重的)showIntAtBase,但我找不到相反的。

【问题讨论】:

  • 这些函数都不能转换为十进制。它们从表示以 2 为基数的数字的字符串转换为机器的本机整数格式,除非您使用一些奇特的硬件,否则它肯定是打包的二进制表示。将 show 函数应用于整数时,会生成一个表示以 10 为底的数字的字符串。

标签: haskell


【解决方案1】:

来自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

【讨论】:

  • 使用右折叠会强制您反转中间列表。为什么不在这里使用 left 折叠呢?
【解决方案2】:

这有帮助吗? 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

【讨论】:

  • 为什么他们先反转然后 foldr 而不是 foldl?
  • @shintoist 我理解其中的区别。我应该说foldl'
  • @shintoist:除非我遗漏了什么,否则该链接中的任何内容都表明foldrreversefoldl' 更可取。事实上,我在这里只能看到使用foldrreverse 的缺点。
  • @sepp2k 不,我同意,我看不出使用 foldr 和反转 foldl' 的理由,但我将问题理解为 foldr 与常规 foldl。
【解决方案3】:

这或多或少是您从 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 的内置实现也可以处理十六进制数字)。
【解决方案4】:

因为

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)

【讨论】:

    【解决方案5】:

    距离最初的帖子已经有一段时间了,但为了未来读者的利益,我会使用以下内容:

    import Data.Char (digitToInt)
    import Data.List (foldl')
    
    toDec :: String -> Int
    toDec = foldl' (\acc x -> acc * 2 + digitToInt x) 0
    

    无需使用^reversezipWithlength 等来减慢速度。

    此外,使用严格折叠可以减少内存需求。

    【讨论】:

      【解决方案6】:
      binario :: Int -> [Int]                      
      binario 1 = [1]                  
      binario n = binario(div x 2)++(mod n 2:[])
      

      感谢@laionzera

      【讨论】:

        【解决方案7】:
        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。)

        【讨论】:

          猜你喜欢
          • 2014-07-26
          • 2018-04-28
          • 1970-01-01
          • 1970-01-01
          • 2012-04-28
          • 2019-06-22
          • 1970-01-01
          • 1970-01-01
          • 2011-08-03
          相关资源
          最近更新 更多