Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Convert big number from decimal to hexadecimal

by ambrus (Abbot)
on Jul 13, 2010 at 13:34 UTC ( #849259=CUFP: print w/ replies, xml ) Need Help??

Today, deMize asked in the chatterbox how to convert the number 4335043554366887798866555766 to hexadecimal. One solution is of course to use dc:

dc -e16o4335043554366887798866555766p

The easiest perl solution is probably to use the Math::BigInt module:

perl -wE 'use Math::BigInt; say Math::BigInt->new("4335043554366887798 +866555766")->as_hex;'

But here's another, more complicated solution.

perl -wE ' sub hadd { no warnings "uninitialized"; my($a, $b) = @_; my @b = @$b; my $c; for (my $k = 0; @b || $c; $k++) { $c = 16 <= ($$a[$k] += $c + shift @b); $$a[$k] %= 16; } } my $n = "4335043554366887798866555766"; my $h = []; for my $d (split //, $n) { hadd $h, $h; hadd my $g = [], $h; hadd $h, $_ for $h, $h, $g, +[$d]; } say join "", reverse map { sprintf "%x", $_; } @$h; '

Update: deleted the unnecessary sub from the code.

Update 2011-03-18: see also Re: Module for 128-bit integer math? for a list of bigint modules.

Update 2012-08-25: see also Re: Zeckendorf representation for another conversion, this time to a more unusual number system.

Comment on Convert big number from decimal to hexadecimal
Select or Download Code
Re: Convert big number from decimal to hexadecimal
by deMize (Monk) on Jul 13, 2010 at 13:45 UTC
    JavaFan also suggested:
    $hex = `echo "obase=16; 4335043554366887798866555766"|bc`; chomp $hex; print $hex;



    Demize
Re: Convert big number from decimal to hexadecimal
by JavaFan (Canon) on Jul 13, 2010 at 13:51 UTC
    $ perl -Mbigint -E 'say 4335043554366887798866555766->as_hex' 0xe01dd2df9232f704e25b376
Re: Convert big number from decimal to hexadecimal
by ambrus (Abbot) on Jul 13, 2010 at 13:55 UTC

    Wait, there's more, we can also adapt Re: Opposite of strtol? like this.

    This goes to the file Tohex.xs:

    #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include <gmp.h> MODULE = Math::Tohex PACKAGE = Math::Tohex SV * tohex(num) char *num CODE: char *out; ST(0) = sv_newmortal(); mpz_t big; mpz_init_set_str(big, num, 10); Newx(out, 4 + mpz_sizeinbase(big, 16), char); mpz_get_str(out, 16, big); sv_setpv(ST(0), out); mpz_clear(big); Safefree(out);

    This goes to the file lib/Math/Tohex.pm:

    package Math::Tohex; require Exporter; require DynaLoader; our $VERSION = "1.00"; our @ISA = (Exporter::, DynaLoader::); our @EXPORT = "tohex"; bootstrap Math::Tohex::; 1; __END__

    And this goes to Makefile.PL:

    use ExtUtils::MakeMaker; WriteMakefile( NAME => "Math::Tohex", VERSION_FROM => "lib/Math/Tohex.pm", LIBS => ["-lgmp"], );

    Now compile:

    perl Makefile.PL && make

    and run:

    perl -wE 'use Math::BigInt; say Math::BigInt->new("4335043554366887798 +866555766")->as_hex;'

    and hope for no stupid mistakes leading to memory corruption.

Re: Convert big number from decimal to hexadecimal
by ambrus (Abbot) on Jul 13, 2010 at 14:44 UTC

    Let me implement the other algorithm too. This one is longer, but you could cut some of it if you reorganized it so that there's only one function doing the work of all three.

    use 5.010; { no warnings "uninitialized"; sub dadd { my($a, $b) = @_; my @b = @$b; my $c; for (my $k = 0; @b || $c; $k++) { $c = 10 <= ($$a[$k] += $c + shift @b); $$a[$k] %= 10; } } sub dsub { my($a, $b) = @_; my @b = @$b; my $c; for (my $k = 0; $k < @$a; $k++) { $c = ($$a[$k] -= $c + shift @b) < 0; $$a[$k] += 10 * $ +c; } $c; } sub dcmp { my($a, $b) = @_; my @a = @$a; my @b = @$b; my $r; while (@a || @b) { if (my $t = shift @a <=> shift @b) { $r = $t; } } $r; } } my $n = [reverse split //, "4335043554366887798866555766"]; my $p = [1]; my $e = 0; while (0 <= dcmp($n, $p)) { dadd $p, $p for 0..3; $e++; } my $r; for my $_e (0 .. $e - 1) { dadd $n, $n for 0..3; my $i = 0; while (0 <= dcmp ($n, $p)) { dsub $n, $p; $i++; } $r .= sprintf "%x", $i; } say $r; __END__

      Okay, here's it a bit shortened:

      use 5.010; sub dalu { no warnings "uninitialized"; my($a, $b, $n, $o) = @_; my @b = @$b; my $c = $n && 1; for (my $k = 0; @b || $k < @$a || $c && !$n; $k++) { my $y = shift @b; $n and $y = 9 - $y; $c = 10 <= (my $z = $$a[$k] + $c + $y); $o or $$a[$k] = $z % 10; } $c; } my $n = [reverse split //, "4335043554366887798866555766"]; my $p = [1]; my $e = 0; while (dalu $n, $p, 1, 1) { dalu $p, $p for 0..3; $e++; } my $r; for my $_e (0 .. $e - 1) { dalu $n, $n for 0..3; my $i = 0; while (dalu $n, $p, 1, 1) { dalu $n, $p, 1; $i++; } $r .= sprintf "%x", $i; } say $r; __END__

      Update: made code a bit nicer.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://849259]
Approved by moritz
Front-paged by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (12)
As of 2014-08-23 13:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (173 votes), past polls