wyvern has asked for the wisdom of the Perl Monks concerning the following question:

Hey everybody. I just need a quick fix for translating decimal values into hexadecimal values, kind of a reverse "hex()" function. I know there's a way to do it with sprintf, but I'm looking for more of an all-purpose translation function. Thanks.

Replies are listed 'Best First'.
Re: Reverse Hexadecimal Translation
by chromatic (Archbishop) on Apr 09, 2000 at 01:27 UTC
    The sprintf() method: my $hex_number = sprintf "%lx", $number; That's the best way I know. Another option would be:
    my %table = ( 'a' => '10', 'b' => '11', 'c' => '12', 'd' => '13', 'e' => '14', 'f' => '15', ); my @numbers = ('a0', '11', 'ff', '9084fe', '10'); foreach my $trial (@numbers) { my @digits = split //, $trial; my $result = 0; foreach my $digit (@digits) { $result *= 16; $result += $digit =~ /\d/ ? $digit : $table{lc($digit)}; } print "$trial is actually $result\n"; }
    I wouldn't do it that way very often, though. The internal conversion routine is much faster.

    modified on 9 April 'cuz btrott is right in his comment, that sneaky japh.

      chromatic wrote:
      > my $dec_number = sprintf "%lx", $number;
      Aren't your variables named backwards here? This sprintf format does decimal->hex translation; your variables make it look like hex->decimal translation.
Re: Reverse Hexadecimal Translation
by jbert (Priest) on Apr 10, 2000 at 18:41 UTC
    "Real Perl Hackers Use 'pack'" (tm)

    If you are happy with it working on a range from 0-255:

    $decimal = 123; $hex = unpack( "H*", pack( "C", $decimal ) ); print "$hex\n";
    Use 'S' or 'L' (for short or long) instead of 'C' to get 16-bit or 32-bit decimal values working.

    You can pack from and unpack to any format described in perlfunc/pack, so it might be described as 'all-purpose'.

    Personally I always get this the wrong way round the first time but when it works it works nicely. Probably efficient too, but who knows.

    If I'm really honest I'd go with 'sprintf', but hey. This is fun too.

Re: Reverse Hexadecimal Translation
by dbrown (Initiate) on Apr 11, 2000 at 07:08 UTC
    I'm not sure what you mean by "all-purpose". Do you want a function that will convert a decimal number to any base (ie base 2)? If you are just concerned with decimal to hex, here ya go:
    # $dec - decimal number to convert to hex
    # $pad - (optional) how long the hex number must be (a minimum).  If
    #        it is not this long, it will be padded with zeros.
    # $x   - (optional) pass 1 if you want the number to have a '0x' at the
    #        beginning. 
    sub toHex
    {
        my ($dec, $pad, $x) = @_;
        my $hex;
        my $str = "%";
    
        $str = "0x" . $str if($x);
        $str .= "0" . $pad if($pad);
        $str .= "x";
        $hex = sprintf($str, $dec);
    
        return $hex;
    }
    
    my $hex1 = toHex(15, 4, 1);
    my $hex2 = toHex(3045);
    my $hex3 = toHex(255, undef, 1);
    
    print "$hex1 $hex2 $hex3\n";
    
    Output:
    0x000f be5 0xff
Re: Reverse Hexadecimal Translation
by btrott (Parson) on Apr 10, 2000 at 05:30 UTC
    You're asking for decimal->hex conversion, right? I'd go with sprintf if I were you. Here's your all-purpose function:
    # forward-declared prototype sub hexify ($); my $hex = hexify 160; print $hex; sub hexify ($) { sprintf "%1x", $_[0]; }