I'm employing Perl for a lot of data crunching, converting between various data formats, etc. There's a nice snippet in the Cookbook named bin2dec - to convert binary numbers (given as strings) to decimals. Like "10011" to "19".

This bin2dec has a limitation of 32 bits, however, because it internally converts to an integer. What I need is bin2dec for binary strings of any length.

Using a full big number library like Math::Bigint for it is a bit of an overkill since I only need binary to decimal conversion. So, I've come up with the following trick:

print bin2dec("1110010101011101111011110110101010111"); # Calculate a (arbitrarily large) decimal number from its # binary representation # sub bin2dec { my ($str) = @_; my $ret = ""; $ret = mul2($ret, $_) foreach split(//, $str); return $ret; } # Given a (arbitrarily large) decimal number N as a string, # returns 2N or 2N+1 # sub mul2 { my ($str, $add_one_f) = @_; defined($add_one_f) or $add_one_f = 0; my $ret = ""; foreach (my $i = length($str) - 1; $i >= 0; --$i) { my $c = substr($str, $i, 1) * 2; $c += 1 if ($add_one_f); $ret = ($c % 10) . $ret; $add_one_f = ($c >= 10); } return $add_one_f ? '1' . $ret : $ret; }
The idea is that there are no long overflows in binary to decimal conversion. I'm shifting the binary number from left to right (msbits first), multiplying by 2 for each shift and adding 1 if the bit is 1. So, all I need is to implement multiplication by 2 (with a possible addition of 1) on string decimals, and that's quite simple (as demonstrated in mul2) because for these operations the carry can be maximum 1.

I'll be glad if someone finds this code useful.

Naturally, ideas for improvements/optimization will be welcomed. My initial implementation was in C++ so this code is a direct translation, and as such can feel "C++ish". More Perlish techniques will be welcomed.


In reply to bin2dec for big numbers by spurperl

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.