Some simple one-liners for encoding and decoding binary-coded decimals (BCD).
# Encode perl -le 'print join " ", map {ord pack "H2", $_} shift =~ /../g' +num # decode perl -le 'print unpack "H*", pack "C*", @ARGV' num1 num2 ... perl -le 'print map {int($_/16).($_%16)} @ARGV' num1 num2 ...

Some examples:

# Encode $ perl -le 'print join " ", map {ord pack "H2", $_} shift =~ /../g +' 019774 1 151 116 # decode $ perl -le 'print unpack "H*", pack "C*", @ARGV' 1 151 116 019774
You can use "h" instead of "H" for low nibble first encoding. Single digit components of the number to be encoded should be zero padded.

--
John.

Replies are listed 'Best First'.
Re: Encode and decode binary-coded decimals
by jryan (Vicar) on Oct 08, 2002 at 16:59 UTC

    I tried all of your snippets, and none seemed to work. For instance:

    perl -le 'print join " ", map {ord pack "H2", $_} shift =~ /../g' 396

    I'd expect to get: 0011 1001 0110, but instead I get 57, which isn't very binary at all :)

    Similarly with decode:

    perl -le 'print unpack "H*", pack "C*", @ARGV' 0011 1001 0110

    Results in 0be96e (hex!) instead of 396.

    These should work:

    # encode perl -e 'print sprintf("%04b ",$_) for shift =~ /\d/g' decimal #decode perl -e '$p=1; map{$l+=oct("0b$_")*$p;$p*=10} reverse @ARGV; print $l' + bcddigit1 bcddigit2 etc

    Update: Updated decoder to use 5.6.1's oct("0b") feature instead of the old perlfaq way to convery binary to decimal.


      In the first case you need to use 0396 instead of 396. That's what the comment about "zero padding" refers to.
      $ perl -le 'print join " ", map {ord pack "H2", $_} shift =~ /../g +' 0396 3 150

      I'd expect to get: 0011 1001 011

      That is at odds with my expectation.:-) Nevertheless, it isn't too difficult to change these routines to support other ascii, hex or binary representations.

      --
      John.

        My definition of BCD is similar to this, but maybe you are referring to something different? :)