Search code examples
binarydc

how do I convert fractional decimal numbers to fractional binary numbers using dc


So dc is a great tool for converting between bases - handy for those bit twiddling coding jobs. e.g to convert 1078 into binary I can do this:

bash> echo "2o1078p" | dc
10000110110

However I can't get it to print fractions between 0 and 1 correctly. Trying to convert 0.3 into binary:

bash> echo "2o10k 0.3p" | dc
.0100

But 0.0100(bin) = 0.25 not 0.3.

However if I construct the value manually I get the right answer

bash> echo "2o10k 3 10 / p" | dc
.0100110011001100110011001100110011

Well it looks like its giving me more than the 10 significant figures I ask for but thats OK

Am I doing something wrong? Or am I trying to make dc do something that its not able to do?

bash> dc --version
dc (GNU bc 1.06) 1.3
...

Solution

  • It seems that dc is getting the number of significant figures from the input.

    Now 1/log10(2)=3.32 so each decimal significant digit is 3.3 binary digits. Looking at the output of dc for varying input SF lengths shows:

    `dc -e "2o10k 0.3 p"` => .0100
    `dc -e "2o10k 0.30 p"` => .0100110
    `dc -e "2o10k 0.300 p"` => .0100110011
    `dc -e "2o10k 0.3000 p"` => .01001100110011
    

    A table of these values and expected value, ceil(log10(2)*SFinput) is as follows:

    input : output : expected output
    1     : 4      : 4
    2     : 7      : 7 
    3     : 10     : 10 
    4     : 14     : 14
    

    And dc is behaving exactly as expected.

    So the solution is to either use the right number of significant figures in the input, or the division form dc -e "2o10k 3 10 / p"