### 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 '
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) {
+[\$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.

Replies are listed 'Best First'.
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;
our \$VERSION = "1.00";
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";
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) {
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.

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

Create A New User
Node Status?
node history
Node Type: CUFP [id://849259]
Approved by moritz
Front-paged by moritz
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2018-04-24 21:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My travels bear the most uncanny semblance to ...

Results (88 votes). Check out past polls.

Notices?