NAME

Math::BaseArith - mixed-base number arithmetic (like APL encode/decode)

SYNOPSIS

  use Math::BaseArith qw( :all );

  encode_base( $value, \@base );

  decode_base( \@representation, \@base );
  
  my @yd_ft_in = (0, 3, 12);

  # convert 175 inches to 4 yards 2 feet 7 inches
  encode_base( 175, \@yd_ft_in ) 

  # convert 4 yards 2 feet 7 inches to 175 inches
  decode_base( [4, 2, 7], \@yd_ft_in )

DESCRIPTION

The inspiration for this module is a pair of functions in the APL programming language called encode (a.k.a. "represent" or "antibase)" and decode (a.k.a. base). Their principal use is to convert numbers from one number base to another. Mixed number bases are permitted.

In this perl implementation, the representation of a number in a particular number base consists of a list reference whose elements are the digit values in that base. For example, the decimal number 31 would be expressed in binary as a list of five ones with any number of leading zeros: [0, 0, 0, 1, 1, 1, 1, 1]. The same number expressed as three hexadecimal (base 16) digits would be [0, 1, 15], while in base 10 it would be [0, 3, 1]. Fifty-one inches would be expressed in yards, feet, inches as [1, 1, 3], an example of a mixed number base.

FUNCTIONS

In the following description of encode_base and decode_base, Q will mean an abstract value or quantity, R will be its representation and B will define the number base. Q will be a perl scalar; R and B are perl lists. The values in R correspond to the radix values in B.

In the examples below, assume the function output is being printed by:

    sub echo { print '=> ', join ', ', @_ }

encode_base

Encode_base is used to represent a number in one or more number bases. The first argument is the number to be converted, and the second argument defines the base (or bases) to be used for the representation. Consider first the representation of a scalar in a single uniform number base:

    encode_base( 2, [2, 2, 2, 2] )
    => 0 0 1 0

    encode_base( 5, [2, 2, 2, 2] )
    => 0 1 0 1

    encode_base( 13, [2, 2, 2, 2] )
    => 1 1 0 1

    encode_base( 62, [16, 16, 16] )
    => 0 3 14

The second argument is called the base list. The length of the base list determines the number of digits in the representation of the first argument. No error occurs if the length is insufficient to give a proper representation of the number. Exploring this situation will suggest other uses of encode_base, and may clarify the use of encode_base with mixed number bases.

    # The representation of 75 in base 4
    encode_base( 75, [4, 4, 4, 4] )
    => 1 0 2 3

    # At least four digits are needed for the full representation
    encode_base( 75, [4, 4, 4] )
    => 0 2 3

    # If fewer elements are in the second argument,
    # leading digits do not appear in the representation.
    encode_base( 75, [4, 4] )
    => 2 3

    # If the second argument is a one-element list reference, encode_base 
    # is identical to modulus (%)
    encode_base( 75, [4] )
    => 3
    encode_base( 76, [4] )
    => 0

    # The expression encode_base( Q, [0] ) always yields Q as the result
    encode_base ( 75, [0] )
    => 75

    # This usage returns quotient and remainder
    encode_base( 75, [0, 4] )
    => 18 3

    # The first quotient (18) is again divided by 4,
    # yielding a second quotient and remainder
    encode_base( 75, [0, 4, 4] )
    => 4 2 3

    # The process is repeated again. Since the last quotient
    # is less than 4, the result is the same as encode_base(75,[4,4,4,4])
    encode_base( 75, [0, 4, 4, 4] )
    => 1 0 2 3

Now consider a mixed number base: convert 175 inches into yards, feet, inches.

    # 175 inches is 14 feet, 7 inches (quotient and remainder).
    encode_base( 175, [0, 12] )
    => 14 7

    # 14 feet is 4 yards, 2 feet,
    encode_base( 14, [0, 3] )
    => 4 2

    # so 175 inches is 4 yards, 2 feet, 7 inches.
    encode_base( 175, [0, 3, 12] )
    => 4 2 7

decode_base

decode_base is used to determine the value of the representation of a quantity in some number base. If R is a list representation (perhaps produced by the encode_base function described above) of some quantity Q in a number base defined by the radix list B (i.e., @R = encode_base($Q,@B), then the expression decode_base(@R,@B) yields $Q:

    decode_base( [0, 0, 1, 0], [2, 2, 2, 2] )
    => 2

    decode_base( [0, 1, 0, 1], [2, 2, 2, 2] )
    => 5

    decode_base( [0, 3, 14], [16, 16, 16]
    => 62

The length of the representation list must be less than or equal to that of the base list.

    decode_base( [1, 1, 1, 1], [2, 2, 2, 2] )
    => 15

    decode_base( [1, 1, 1, 1], [2] )
    => 15

    decode_base( [1], [2, 2, 2, 2] )
    => 15

    decode_base( [1, 1, 1, 1], [2, 2, 2] )
    => (void)
    raises a LENGTH ERROR

As with the encode_base function, mixed number bases can be used:

    # Convert 4 yards, 2 feet, 7 inches to inches.
    decode_base( [4, 2, 7], [0, 3, 12] )
    => 175

    # Convert 2 days, 3 hours, 5 minutes, and 27 seconds to seconds
    decode_base( [2, 3, 5, 27], [0, 24, 60, 60] )
    => 183927

    # or to minutes.
    decode_base( [2, 3, 5, 27], [0, 24, 60, 60] ) / 60
    => 3065.45

The first element of the radix list (second argument) is not used; it is required only to make the lengths match and so can be any value.

DEPRECATED FUNCTIONS

encode
decode

Synonmous with encode_base/decode_base. Imported by default. See COMPATIBILITY for details.

COMPATIBILITY

When this module was originally released on CPAN in 2002, it exported the functions encode and decode by default. These function names, however, are fairly common and so have a high probability of colliding in the global namespace with those from other modules. As of version 1.02, the functions were renamed encode_base and decode_base in order to better distinguish them.

For upward compatibility, encode/decode are provided as aliases for encode_base/decode_base and are still exported by default so scripts that include the module by:

    use Math::BaseArith;

will continue to work unchanged. See the EXPORT section for the preferred way to include the module from version 1.02 ownward.

Note the the keyword :old can be used to specify the old function names (encode/decode). The most likely use of this is to exclude them from the namespace so you can then include just one of them. For example, to get decode without encode you can do this:

    use Math::BaseArith qw( !:old decode );

But, rather than this approach, consider altering your code to use the new and preferred function names.

EXPORT

As of version 1.02 and above, the preferred way to include this module is by using :all, or specifying you want either encode_base or decode_base:

    use Math::BaseArith ':all';
or
    use Math::BaseArith 'encode_base';
or
    use Math::BaseArith 'decode_base';
    

Do NOT include it without parameters, as that will automatically import the old function names encode/decode.

DEBUGGING

Set the global variable $Math::BaseArith::DEBUG to print debugging information to STDERR.

If set to 1, function names and parameters are printed.

If set to 2, intermediate results are also printed.

LIMITATIONS

The APL encode function allows both arguments to be a list, in which case the function evaluates in dot-product fashion, generating a matrix whose columns are the representation vectors for each value in the value list; i.e. a call such as encode_base([15,31,32,33,75],[4,4,4,4]) would generate the following matrix;

        0 0 0 0 1
        0 1 2 2 0
        3 3 0 0 2
        3 3 0 1 3

This version of encode_base supports only a scalar value as the first argument.

The APL version of decode support non-integer values. This version doesn't.

SEE ALSO

https://aplwiki.com/wiki/Encode

https://aplwiki.com/wiki/Decode

AUTHOR

PUCKERING, Gary Puckering <jgpuckering@rogers.com>

BUGS

Please report any bugs or feature requests to bug-math-basearith at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Math-BaseArith. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Math::BaseArith

You can also look for information at:

ACKNOWLEDGEMENTS

Kenneth E. Iverson, inventor of APL and author of "A Programming Language", John Wiley & Sons, 1962

COPYRIGHT AND LICENSE

Copyright (c) 2002, Gary Puckering. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl 5. For more details, see the full text of the licenses in the directory LICENSES. This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.