Non-decimal radices/Convert: Difference between revisions
Content added Content deleted
(→{{header|PARI/GP}}: Loop was going wrong direction.) |
(→{{header|Perl}}: Simple builtins, rewrite code, show modules.) |
||
Line 1,743: | Line 1,743: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
For base 2 and 16, we can do this entirely with language features: |
|||
To parse from a base: |
|||
<lang perl> |
<lang perl>sub to2 { 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 { |
|||
⚫ | |||
⚫ | |||
while ($n) { |
|||
⚫ | |||
⚫ | |||
} |
|||
⚫ | |||
} |
|||
sub base_from { |
|||
my($n,$b) = @_; |
|||
⚫ | |||
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); |
my ($num, $n_unparsed) = strtol('1a', 16); |
||
$n_unparsed == 0 or die "invalid characters found"; |
$n_unparsed == 0 or die "invalid characters found"; |
||
print "$num\n"; # prints "26"</lang> |
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> |
<lang perl>use ntheory qw/fromdigits todigitstring/; |
||
my $n = 65261; |
|||
# Converts an integer to a single digit. |
|||
my $n16 = todigitstring($n, 16) || 0; |
|||
my $n10 = fromdigits($n16, 16); |
|||
⚫ | |||
say "$n $n16 $n10"; # prints "65261 feed 65261"</lang> |
|||
? $i |
|||
⚫ | |||
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] |
|||
⚫ | |||
* [https://metacpan.org/pod/Math::NumberBase Math::NumberBase] |
|||
⚫ | |||
* [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] |
|||
⚫ | |||
⚫ | |||
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}}== |
=={{header|Perl 6}}== |