George Mauer
George Mauer

Reputation: 122092

Convert binary string to number

Pretty straightforward, but I can't seem to find an answer. I have a string of 1s and 0s such as "01001010" - how would I parse that into a number?

Upvotes: 5

Views: 1208

Answers (4)

Indinfer
Indinfer

Reputation: 97

This thread has an elisp tag. Because it also has a lisp tag, I would like to show standard Common Lisp versions of two solutions. I checked these on LispWorks only. If my solutions are not standard Common Lisp, maybe someone will correct and improve my solutions.

For solutions

(string-to-number "01001010" 2)

and

(cl-parse-integer "001010" :radix 2)

LispWorks does not have string-to-number and does not have cl-parse-integer. In LispWorks, you can use:

(parse-integer "01001010" :radix 2)

For the solution

(read (concat "#2r" STRING))

LispWorks does not have concat. You can use concatenate instead. read won't work on strings in LispWorks. You have to give read a stream.

In LispWorks, you can do this:

(read (make-string-input-stream (concatenate 'string "#2r" "01001010")))

You can also use format like this:

(read (make-string-input-stream (format nil "#2r~a" "01001010")))

Upvotes: 2

coredump
coredump

Reputation: 38809

As explained by @sds in a comment, string-to-number returns 0 if the conversion fails. This is unfortunate, since a return value of 0 could also means that the parsing succeeded. I'd rather use the Common Lisp version of this function, cl-parse-integer. The standard function is described in the Hyperspec, whereas the one in Emacs Lisp is slightly different (in particular, there is no secondary return value):

(cl-parse-integer STRING &key START END RADIX JUNK-ALLOWED)

Parse integer from the substring of STRING from START to END. STRING may be surrounded by whitespace chars (chars with syntax ‘ ’). Other non-digit chars are considered junk. RADIX is an integer between 2 and 36, the default is 10. Signal an error if the substring between START and END cannot be parsed as an integer unless JUNK-ALLOWED is non-nil.

(cl-parse-integer "001010" :radix 2)
=> 10

(cl-parse-integer "0" :radix 2)
=> 0

;; exception on parse error
(cl-parse-integer "no" :radix 2)
=> Debugger: (error "Not an integer string: ‘no’")

;; no exception, but nil in case of errors
(cl-parse-integer "no" :radix 2 :junk-allowed t)
=> nil

;; no exception, parse as much as possible
(cl-parse-integer "010no" :radix 2 :junk-allowed t)
=> 2

Upvotes: 6

phils
phils

Reputation: 73274

This seems hacky by comparison, but FWIW you could also do this:

(read (concat "#2r" STRING))

i.e. read a single expression from STRING as a binary number.

This method will signal an error if the expression isn't valid.

Upvotes: 1

Amadan
Amadan

Reputation: 198324

Use string-to-number, which optionally accepts the base:

(string-to-number "01001010" 2)
;; 74

Upvotes: 7

Related Questions