20

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.

Johanna Larsson
  • 10,531
  • 6
  • 39
  • 50
  • None of these functions convert to decimal. They convert from a string representing a number in base 2 to the machine's native integer format, which, unless you are using some exotic hardware, is most assuredly a packed binary representation. It is the show function that, when applied to the integer, generates a string representing the number in base 10. – pat Sep 29 '15 at 16:16

7 Answers7

23

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.

iceman
  • 2,020
  • 2
  • 17
  • 24
15

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
ACoolie
  • 1,429
  • 1
  • 12
  • 16
  • One can also use `digitToInt = subtract (fromEnum '0') . fromEnum` instead, which works for all decimal digits (the built-in implementation of `digitToInt` handles hexadecimal digits as well). – Rufflewind Jan 16 '14 at 00:27
3

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
eggyal
  • 122,705
  • 18
  • 212
  • 237
  • 1
    Using a right fold forces you to reverse the intermediate list. Why not use a *left* fold, here, instead? – jub0bs Jul 16 '15 at 18:36
2

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
clt60
  • 62,119
  • 17
  • 107
  • 194
  • 2
    Why do they reverse and then foldr instead of foldl? – alternative May 07 '11 at 14:20
  • @mathepic http://stackoverflow.com/questions/384797/implications-of-foldr-vs-foldl-or-foldl – Johanna Larsson May 07 '11 at 14:30
  • @shintoist I understand the difference. I should have said `foldl'` – alternative May 07 '11 at 15:10
  • 1
    @shintoist: Unless I'm missing something, nothing in that link suggests that `foldr` and `reverse` are preferable to `foldl'` here. As a matter of fact, I can only see downsides to using `foldr` and `reverse` here. – sepp2k May 07 '11 at 15:12
  • @sepp2k no, I agree, I don't see a reason either to using foldr and reverse over foldl', but I understood the question as foldr vs regular foldl. – Johanna Larsson May 07 '11 at 19:41
  • I'm +1ing this despite the fact that I normally don't +1 sloppy code (ie reverse then foldr) that is copied but not looked over, only because there is another answer, exactly the same, that had one more upvote. – alternative May 07 '11 at 21:57
1

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)
Zane XY
  • 2,743
  • 1
  • 22
  • 12
0
binario :: Int -> [Int]                      
binario 1 = [1]                  
binario n = binario(div x 2)++(mod n 2:[])

credits to @laionzera

jrbedard
  • 3,662
  • 5
  • 30
  • 34
0
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.)

Steerio
  • 1
  • 1