Johanna Larsson
Johanna Larsson

Reputation: 10761

Convert a string representing a binary number to a base 10 string haskell

I have the string "1001" and I want the string "9".

The numeric library has the (rather clunky) showIntAtBase, but I haven't been able to find the opposite.

Upvotes: 20

Views: 14329

Answers (7)

Steerio
Steerio

Reputation: 1

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

(Of course you might want to return Nothing on empty string in the second one as well.)

Upvotes: 0

Duwan Bassani
Duwan Bassani

Reputation: 1

binario :: Int -> [Int]                      
binario 1 = [1]                  
binario n = binario(div x 2)++(mod n 2:[])

credits to @laionzera

Upvotes: 0

iceman
iceman

Reputation: 2130

It's been a while since the original post but, for future readers' benefit, I would use the following:

import Data.Char (digitToInt)
import Data.List (foldl')

toDec :: String -> Int
toDec = foldl' (\acc x -> acc * 2 + digitToInt x) 0

No need to slow things down by using ^, reverse, zipWith, length, etc.

Also, using a strict fold reduces memory requirements.

Upvotes: 23

Zane XY
Zane XY

Reputation: 2799

Because

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│
└───┴───┴───┴───┘

so obviously:

fromBinary :: String -> Int
fromBinary str = sum $ zipWith toDec (reverse str) [0 .. length str]
  where toDec a b = digitToInt a * (2 ^ b)

Upvotes: 1

ACoolie
ACoolie

Reputation: 1439

Here is more or less what you were looking for from Prelude. From Numeric:

(NB: readInt is the "dual" of showIntAtBase, and readDec is the "dual" of showInt. The inconsistent naming is a historical accident.)

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

Upvotes: 15

clt60
clt60

Reputation: 63892

This helps? http://pleac.sourceforge.net/pleac_haskell/numbers.html

from the page:

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

Upvotes: 2

eggyal
eggyal

Reputation: 125835

From 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

Upvotes: 3

Related Questions