5

I know of bc:

$> var="304"
$> echo "obase=2; $var" | bc
100110000

Could it be done in shell (no external call)?

This question: Binary to hexadecimal and decimal in a shell script Asks how to convert FROM binary, not TO a binary number.

The answers there deal either with binary byte (as opposed to binary number, i.e.: a base-2 number) using xxd, or some other external tool. So, no, this question is not a duplicate of that.

  • 3
    possible duplicate of Binary to hexadecimal and decimal in a shell script – cuonglm Aug 15 '15 at 3:28
  • You should read the answer from Stéphane Chazelas, it contain all things you want. – cuonglm Aug 15 '15 at 3:49
  • Explained in the question, but it must be obvious that all answers in the question linked used external commands. None used a shell script. That is something not done before. – user79743 Aug 15 '15 at 3:50
  • All solution in that answer using shell script, it's only not POSIX. It can be better if you can stick your solution with that question. – cuonglm Aug 15 '15 at 3:54
  • That answer you link has very good points for the question asked there. And solves some parts of the problem only for ksh and/or zsh. There is no solution usable in bash, for example. Even worse, there is no attempt to make a portable solution. – user79743 Aug 15 '15 at 4:05
6

In bash:

toBinary(){
    local n bit
    for (( n=$1 ; n>0 ; n >>= 1 )); do  bit="$(( n&1 ))$bit"; done
    printf "%s\n" "$bit"
}

Use:

$> toBinary 304
100110000

Or more POSIX_ly:

toBinaryPOSIX(){
    n="$1"
    bit="" 
    while [ "$n" -gt 0 ]; do
        bit="$(( n&1 ))$bit";
        : $(( n >>= 1 ))
    done
    printf "%s\n" "$bit"
}

Use:

$> toBinaryPOSIX 304
100110000

If Value is hex:

$> toBinaryPOSIX "$(( 0x63 ))"
1100011
  • local is not in POSIX. – cuonglm Aug 15 '15 at 2:47
2

perl is good tool for this job:

$ var="304"
$ perl -e 'printf "%b\n",'$var
100110000
1

The following solution uses builtins only to convert number to binary form:

#! /bin/sh

E=[24680] # even nums
O=[13579] # odd  nums

lookuptbl() {
   case $1 in
      $E[01]* ) echo 0 ;; $E[23]* ) echo 1 ;;
      $E[45]* ) echo 2 ;; $E[67]* ) echo 3 ;;
      $E[89]* ) echo 4 ;; $O[01]* ) echo 5 ;;
      $O[23]* ) echo 6 ;; $O[45]* ) echo 7 ;;
      $O[67]* ) echo 8 ;; $O[89]* ) echo 9 ;;
   esac
}

divby2() {
   set -- "0$1"

   while case $1 in ? ) break ;; esac; do
      set -- "${1#?}" "${2-}$(lookuptbl "$1")"
   done

   echo $2
}

dec2bin() {
   case $1 in *[!0]* ) :;; * ) echo 0; return ;; esac

   while :
   do
      case $1 in *[!0]* ) :;; * ) break;; esac
      case $1 in
         *$E ) set -- "$(divby2 "$1")" "0${2-}" ;;
         *$O ) set -- "$(divby2 "$1")" "1${2-}" ;;
      esac
   done

   echo "$2"
}

# And then... (assuming pure number given from command line)
num=${1:-304}
dec2bin "$num"

result

100110000
0

You can use the POSIX Awk stdlib library:

$ awklib 'BEGIN {print base_conv(304, 10, 2)}'
100110000

Or:

$ awklib 'BEGIN {print base_conv(ARGV[1], 10, 2)}' 304
100110000
0

With ksh or zsh:

$ typeset -i2 n=304
$ echo "$n"
2#100110000
$ echo "${n#*#}"
100110000

With zsh:

$ echo $(([##2]304))
100110000

With ksh93:

$ printf '%..2d\n' 304
100110000

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy