Velocity Reviews > Perl > Math problem - converting between arbitrary bases in perl - help!

Math problem - converting between arbitrary bases in perl - help!

! aaa
Guest
Posts: n/a

 05-27-2004
Hi all - I've been trying to write a small sub to convert form an input base
(eg: 16) to an output base (eg:64) and back.

The reason is that I need to communicate tristate (base 3) data efficiently
via DNS (base 37 a-z0-9 and '-').

I *could* do it by converting into a "bigmath binary" structure I guess, but
I thought there might be a more elegant way...

but such a solution eludes me.

Can anyone think how to approach the problem?

Below is my NON-working attempt. I thought of creating a "buffer" (I called
it \$remainder) through which I can
convert incoming stuff to the outgoing stuff, but (A) I'm not sure if this
is even possible, and (B) if so, I'm lost
near the end, where I'm "nibbling off" parts of the \$remainder variable as I
output results. In short. I'm wrong
there someplace

# Sorry I forgot to comment it )

#!perl

use strict;

# my(\$from_base)=10; my(\$to_base)=94; my(\$data)='92356234';
# my(\$from_base)=10; my(\$to_base)=16; my(\$data)='283036414'; # 283036414
should be 10DECAFE in hex
my(\$from_base)=16; my(\$to_base)=10; my(\$data)='C0DECAFE'; # 283036414 should
be 10DECAFE in hex

my \$b2 = &baseconv(\$from_base,\$to_base,\$data);
print "Base\$from_base(\$data)=Base\$to_base(\$b2)\n";

sub baseconv {
my(\$from_base,\$to_base,\$data)=@_;
my
\$collseq='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcd efghijklmnopqrstuvwxyz!"#\$
%&\'()*+,-./:;<=>?@[\]^_`{|}~'; # 94 "digits"
my \$remainder=0; my \$pow=0; my \$ret=''; my \$tmp; my \$mop=0;
while((\$data ne '')||(\$remainder)) {
\$remainder+=index(\$collseq,chop \$data)*(\$from_base**(\$pow++))
while((\$data ne '')&&(\$remainder<((\$to_base*\$from_base)**2)));
print "remainder=\$remainder\n";

my(\$tgt)=(\$to_base*\$from_base)**2; \$mop=0;
while(((\$tgt % \$from_base)==0)||((\$data eq '')&&(\$remainder>0))) {
\$pow--; \$tgt=\$tgt/\$from_base;
\$tmp=\$remainder % \$to_base;
\$ret.=substr(\$collseq,\$tmp,1); \$remainder=(\$remainder-\$tmp)/\$to_base;
print "ret=\$ret data=\$data remainder=\$remainder tgt=\$tgt\n";
exit(0) if(\$pow<-10);
}

# while((\$remainder>=\$to_base)||(\$data eq '')) { \$tmp=\$remainder %
\$to_base; \$ret.=substr(\$collseq,\$tmp,1); \$remainder=(\$remaind
er-\$tmp)/\$to_base; }

print "ret=\$ret\n";
}
return reverse(\$ret);
}

! aaa
Guest
Posts: n/a

 05-28-2004
p.s. I forgot to mention - arbitrary sized numbers - eg: not restricted to
2^32 (base 10)
or other machine constraints.