# base($number, $inbase, $outbase) transforms a number from one
# base to another.
#
# Examples:
# base(17, 9, 2) converts 17 (base 9) to base 2: 10000.
# base("fff", 16, 3) converts fff (base 16) to base 3: 12121200.
# base("g", 17, 10) converts g (base 17) to base 10: 16.
#
# Uses the logbase() function defined below.
#
# Returns undef on error.
#
sub base {
my ($number, $inbase, $outbase) = @_;
my ($realnum, $output, $i, $digit);
# Convert the number (which might have letters) to lowercase.
$number = lc($number);
# Return undef (or an empty list) if the base is too weird.
return if $inbase > 36 or $outbase > 36 or
$inbase < 2 or $outbase < 2;
# Convert $number from base $inbase to base 10.
for $digit (reverse split(//, $number)) {
$digit = ord($digit) - 87 if ord($digit) > 96;
return if $digit >= $inbase;
$realnum += $digit * ($inbase ** $i++);
}
# Convert the number from base 10 to $outbase.
# logbase() is defined below.
for ($i = int(logbase($realnum, $outbase)); $i >= 0; $i--) {
$digit = int($realnum / ($outbase ** $i));
$realnum -= $digit * ($outbase ** $i);
$digit = ord($digit + 49) if ord($digit) > 57;
$output .= $digit;
}
return $output;
}
# base(17, 9, 2) converts 17 (base 9) to base 2: 10000.
print base(17, 9, 2), "\n";
# base("fff", 16, 3) converts fff (base 16) to base 3: 12121200.
print base("fff", 16, 3), "\n";
# base("g", 17, 10) converts g (base 17) to base 10: 16.
print base("g", 17, 10), "\n";
# logbase($number, $base) computes the logarithm of number in base $base.
#
# Example: logbase(243, 3) is 5, because 3 ** 5 is 243.
#
sub logbase {
my ($number, $base) = @_;
return if $number <= 0 or $base <= 0 or $base == 1;
return log($number) / log($base);
}