NAME

Math::Currency - Exact Currency Math with Formatting and Rounding

SYNOPSIS

use Math::Currency qw(Money $LC_MONETARY);
$dollar = Math::Currency->new("$12,345.67");
$taxamt = $dollar * 0.28;
# this sets the default format for all objects w/o their own format
Math::Currency->format( $LC_MONETARY->{EUR} );
$euro = Money(12345.67);
$euro_string = Money(12345.67)->bstr();
# or if you already have a Math::Currency object
$euro_string = "$euro";

DESCRIPTION

Currency math is actually more closely related to integer math than it is to floating point math. Rounding errors on addition and subtraction are not allowed and division/multiplication should never create more accuracy than the original values. All currency values should round to the closest cent or whatever the local equivalent should happen to be.

All common mathematical operations are overloaded, so once you initialize a currency variable, you can treat it like any number and the module will do the right thing. This module is a thin layer over Math::BigFloat which is itself a layer over Math::BigInt.

Output Formatting

Each currency value can have an individual format or the global currency format can be changed to reflect local usage. I used the suggestions in Tom Christiansen's PerlTootC to implement translucent attributes. If you have set your locale values correctly, this module will pick up your local settings or US standards if you haven't.

Currency Symbol

The locale definition includes two different Currency Symbol strings: one is the native character(s), like $ or £ or DM; the other is the three character string defined by the ISO4217 specification followed by the normal currency seperation character (frequently space). The default behavior is to always display the native CURRENCY_SYMBOL unless a global parameter is set:

$Math::Currency::use_int = 1; # print the currency symbol text

where the INT_CURR_SYMBOL text will used instead.

Predefined Locales

There are currently three predefined Locale LC_MONETARY formats:

USD = United States dollars (the default if no locale)
EUR = One possible Euro format (no single standard, yet)
GBP = British Pounds Sterling

These hashes can be retrieved using the optional export $LC_MONETARY, like this:

$format = $LC_MONETARY->{EUR};

This $format hash can be used to set either object formats (see "Object Formats") or can be used to set the package format (see "Global Format") that all objects will inherit by default.

Global Format

Global formatting can be changed by setting the package global format like this:

Math::Currency->format($LC_MONETARY->{USD});

Object Formats

Any object can have it's own format different from the current global format, like this:

$pounds  = Math::Currency->new(1000, $LC_MONETARY->{GBP});
$dollars = Math::Currency->new(1000); # inherits default US format
$dollars->format( $LC_MONETARY->{USD} ); # explicit object format

Format Parameters

The format has must contains all of the commonly configured LC_MONETARY Locale settings. For example, these are the values of the default US format (with comments):

{
  INT_CURR_SYMBOL    => 'USD',  # ISO currency text
  CURRENCY_SYMBOL    => '$',    # Local currency character
  MON_DECIMAL_POINT  => '.',    # Decimal seperator
  MON_THOUSANDS_SEP  => ',',    # Thousands seperator
  MON_GROUPING       => '3',    # Grouping digits
  POSITIVE_SIGN      => '',     # Local positive sign (see below)
  NEGATIVE_SIGN      => '-',    # Local negative sign (see below)
  INT_FRAC_DIGITS    => '2',    # Default Intl. precision
  FRAC_DIGITS        => '2',    # Local precision
  P_CS_PRECEDES      => '1',    # Currency symbol location
  P_SEP_BY_SPACE     => '0',    # Space between Currency and value
  N_CS_PRECEDES      => '1',    # Negative version of above
  N_SEP_BY_SPACE     => '0',    # Negative version of above
  P_SIGN_POSN        => '1',    # Position of positive sign (see below)
  N_SIGN_POSN        => '1',    # Position of negative sign (see below)
}

Each of the formatting parameters can be individually changed at the object or class (global) level; if an object is currently sharing the global format, all the global parameters will be copied prior to setting the overrided parameters. For example:

$dollars = Math::Currency->new(1000); # inherits default US format
$dollars->format('CURRENCY_SYMBOL',' Bucks'); # now has its own format
$dollars->format('P_CS_PRECEDES',0); # now has its own format
print $dollars; # displays as "1000 Bucks"

Or you can also set individual elements of the current global format:

Math::Currency->format('CURRENCY_SYMBOL',' Bucks'); # global changed

The [NP]_SIGN_POSN parameter determines how positive and negative signs are displayed. [NP]_CS_PRECEEDS determines where the currency symbol is shown. [NP]_SEP_BY_SPACE determines whether the currency symbol cuddles the value or not. The following table shows the relationship between these three parameters:

                                              p_sep_by_space
                                        0          1          2

p_cs_precedes = 0   p_sign_posn = 0    (1.25$)    (1.25 $)   (1.25 $)
                    p_sign_posn = 1    +1.25$     +1.25 $    +1.25 $
                    p_sign_posn = 2     1.25$+     1.25 $+    1.25$ +
                    p_sign_posn = 3     1.25+$     1.25 +$    1.25+ $
                    p_sign_posn = 4     1.25$+     1.25 $+    1.25$ +

p_cs_precedes = 1   p_sign_posn = 0   ($1.25)   ($ 1.25)   ($ 1.25)
                    p_sign_posn = 1   +$1.25    +$ 1.25    + $1.25
                    p_sign_posn = 2    $1.25+    $ 1.25+     $1.25 +
                    p_sign_posn = 3   +$1.25    +$ 1.25    + $1.25
                    p_sign_posn = 4   $+1.25    $+ 1.25    $ +1.25

(the negative variants are similar).

AUTHOR

John Peacock <jpeacock@rowman.com>

SEE ALSO

perl(1). perllocale Math::BigFloat Math::BigInt

1 POD Error

The following errors were encountered while parsing the POD:

Around line 341:

Non-ASCII character seen before =encoding in '£'. Assuming CP1252