Math::Fleximal - Integers with flexible representations.
use Math::Fleximal; my $number = new Math::Fleximal($value, $flex); # Set the value $number = $number->set_value("- $fleck_4$fleck_3"); $number = $number->set_value($another_number); # Get the object in a familiar form my $string = $number->to_str(); my $integer = $number->base_10(); # Construct more numbers with same flex my $copy = $number->dup(); my $other_number = $number->dup($value); my $absolute_value = $number->abs(); # New representation anyone? my $in_new_base = $number->change_flex($new_flex); # Arithmetic - can be different flex. Answers have # the flex of $number. $result = $number->add($other_number); $result = $number->mul($other_number); $result = $number->subtr($other_numer); $result = $number->div($other_number); # And integer-specific arithmetic works $result = $number->gcd($other_number); $result = $number->mod($other_number); my $comparison = $number->cmp($other_number);
This is a package for doing integer arithmetic while using a different base representation than normal. In base n arithmetic you have n symbols which have a representation. I was going to call them "glyphs", but being text strings they are not really. On Tye McQueen's whimsical suggestion I settled on the name Math::Fleximal, the set of text representations is called a "flex", and the representation of individual digits are the "flecks". These names are somewhat unofficial...
This allows you to do basic arithmetic using whatever digits you want, and to convert from one to another.
Like Math::BigInt
it is able to handle very large numbers, though performance is not very good. (Which is also like Math::BigInt
, for good performance you should be using <Bit::Vector>.) Instead use it as a version of Math::BaseCalc without an upper limit on the size of numbers. A sample use would be to put an MD5 hash into a convenient representation:
use Math::Fleximal; use Digest::MD5 qw(md5_hex); my $digest = hex2alpha(md5_hex($data)); # Converts a hex representation of a number into # one that uses more alphanumerics. (ie base 62) sub hex2alpha { Math::Fleximal->new( lc(shift), [0..9, 'a'..'f'] )->change_flex( [0..9,'a'..'z','A'..'Z'] )->to_str(); }
new
Construct a new number. The arguments are the value, the anonymous array of flecks that make up the flex, followed by an anonymous hash of other arguments. The flex will default to [0..9] and the other arguments will default to an empty hash.
This can be used to calculations in bases other than 10 - the base is just the number of flecks in the flex. So you could construct a base 16 number with:
my $base_16 = new Math::Fleximal("4d", [0..9, 'a'..'f']);
If a value is passed it can be an existing Math::Fleximal or (as above) a string that can be parsed with the current flex.
The possible keys to the optional arguments are:
The parsing of a string into flecks is case sensitive. Also possibly ambiguous parses are not handled very well.
dup
Copy an existing number. This copy may be worked with without changing the existing number. If dup is passed a value, the new instance will have that value instead.
set_value
This sets the internal value and returns the object.
You can either pass the new value an existing instance (which may be in another base) or a string. When passed a string it first strips whitespace. After that it accepts an optional +-, followed by a series of flecks (there must be at least one) for the first to last digits. It will be confused if the leading fleck starts with + or - and no sign is included.
to_str
Returns the string representation of the current value using the current flex. This always includes a sign, with no white space in front of the sign.
base_10
Returns the internal value in a base 10 representation. The numbers returned may be larger than Perl's usual integer representation can handle.
change_flex
Takes a new flex and converts the current to that. Will implicitly change base if needed.
add
Adds one or more numbers to the current one and returns the answer in the current representation. The numbers may be objects in any base, or strings of the current representation.
mul
Multiplies one or more numbers to the current one and returns the answer in the current representation. The numbers may be objects in any base, or strings of the current representation.
subtr
Subtracts one or more numbers from the current one and returns the answer in the current representation. The numbers may be objects in any base, or strings of the current representation.
div
Divides one or more numbers from the current one and returns the answer in the current representation. In list context it will return the answer and an array of remainders in the current representation. The remainders will be positive and less than the absolute value of the denominator. The numbers may be objects in any base, or strings of the current representation.
gcd
Takes one or more numbers and calculates the gcd of this and the entire list.
mod
Does the divisions as div
does and returns only the remainders. In scalar context only the last remainder is returned. Thus the following returns the ten-thousands digit:
my $digit = $number->mod(1000, 10);
cmp
Pass another number, returns -1 if it is smaller than the other number, 0 if they are equal, and 1 if it is larger. (Much like cmp does with strings.)
one
Returns 1 in the current flex.
zero
Returns 0 in the current flex.
This will fail if you are trying to work in bases of size more than 30,000 or so.
Only a slight effort is made to resolve potential ambiguities in the parsing of a string into flecks.
Copyright 2000-2001, Ben Tilly (<btilly@gmail.com>)
Math::Fleximal may be copied and distributed on the same terms as Perl itself.