Non-decimal radices/Convert: Difference between revisions

→‎{{header|Perl}}: Simple builtins, rewrite code, show modules.
(→‎{{header|PARI/GP}}: Loop was going wrong direction.)
(→‎{{header|Perl}}: Simple builtins, rewrite code, show modules.)
Line 1,743:
 
=={{header|Perl}}==
For base 2 and 16, we can do this entirely with language features:
To parse from a base:
<lang perl>usesub POSIXto2 { sprintf "%b", shift; }
sub to16 { sprintf "%x", shift; }
sub from2 { unpack("N", pack("B32", substr("0" x 32 . shift, -32))); }
sub from16 { hex(shift); }</lang>
 
Small functions will handle arbitrary base conversions for bases 2-36:
<lang perl>sub base_to {
{my my($intn, $radixb) = @_;
my $numerals = ''"";
while ($n) {
:$s .= ('0'..'9','a' .. 'z')[$in -% 10$b];}
} while $intn = int($int n/ $radixb);
}
scalar (reverse ($numerals));}</lang>
}
sub base_from {
my($n,$b) = @_;
my $it <= 100;
for my $c (split(//, lc($n))) {
$t = $b * $t + index("0123456789abcdefghijklmnopqrstuvwxyz", $c);
}
$t;
}</lang>
 
There are a plethora of modules that perform base conversion.
 
The core [https://metacpan.org/pod/distribution/perl/ext/POSIX/lib/POSIX.pod POSIX] module includes strtol (and strtoul) which is simple and fast, but only does conversions from a base. On some platforms the function may be limited to 32-bit even with a 64-bit Perl.
<lang perl>use POSIX;
my ($num, $n_unparsed) = strtol('1a', 16);
$n_unparsed == 0 or die "invalid characters found";
print "$num\n"; # prints "26"</lang>
 
The [https://metacpan.org/pod/ntheory ntheory] module includes functions that will perform base conversion, and is fast. It supports bases up to 36 and bigints.
To format into a base:
<lang perl>subuse digitizentheory qw/fromdigits todigitstring/;
my $n = 65261;
# Converts an integer to a single digit.
{my $in16 = shifttodigitstring($n, 16) || 0;
my $n10 = fromdigits($n16, 16);
$i < 10
say "$n $n16 $n10"; # prints "65261 feed 65261"</lang>
? $i
 
: ('a' .. 'z')[$i - 10];}
Other modules include but are not limited to:
 
* [https://metacpan.org/pod/Math::BaseCalc Math::BaseCalc]
sub to_base
* [https://metacpan.org/pod/Math::Int2Base Math::Int2Base]
{my ($int, $radix) = @_;
* [https://metacpan.org/pod/Math::NumberBase Math::NumberBase]
my $numeral = '';
* [https://metacpan.org/pod/Convert::AnyBase Convert::AnyBase]
do {
* [https://metacpan.org/pod/Math::BaseCnv Math::BaseCnv]
$numeral .= digitize($int % $radix);
* [https://metacpan.org/pod/Math::BaseConvert Math::BaseConvert]
} while $int = int($int / $radix);
scalar reverse $numeral;}</lang>
 
The last two are ''much'' slower than the others or the simple functions above, but may have extra features. Math::Base::Convert and Convert::BaseN are currently not recommended.
<code>Math::BaseCnv</code> can convert an integer to or from an
arbitrary other base. Its normal output is upper-case but the usual
<code>lc()</code> can convert (cf [[String case#Perl|String case]]).
<lang Perl>use Math::BaseCnv 'cnv';
print cnv("1a", 16, 10),"\n"; # "1a" from hex to decimal prints 26
print lc(cnv(26, 10, 16)),"\n"; # 26 from decimal to hex prints "1a"</lang>
 
The module [https://metacpan.org/pod/Math::Fleximal Math::Fleximal] not only does very arbitrary base conversion, but allows computations in different bases.
<code>Math::BaseCalc</code> can do similar conversions with an
arbitrary set of characters for digits.
 
=={{header|Perl 6}}==
Anonymous user