.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Math::Currency 3" .TH Math::Currency 3 "2008-01-07" "perl v5.8.8" "User Contributed Perl Documentation" .SH "NAME" Math::Currency \- Exact Currency Math with Formatting and Rounding .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 9 \& 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('EUR'); \& $euro = Money(12345.67); \& $euro_string = Money(12345.67)->bstr(); \& # or if you already have a Math::Currency object \& $euro_string = "$euro"; .Ve .SH "DESCRIPTION" .IX Header "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. .PP However, repeated mathematical operations on currency values can lead to inaccurate results, if rounding is performed at each intermediate step. In order to preserve appropriate accuracy, the Math::Currency values are stored with an additional two places of accuracy internally and only rounded to the \*(L"correct\*(R" precision when the value is displayed (either by the default stringification or through the use of as_float or as_int). .PP 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. .SH "Important Note on Input Values" .IX Header "Important Note on Input Values" Since the point of this module is to perform currency math and not floating point math, it is important to understand how the initial value passed to \fInew()\fR may have nasty side effects if done improperly. Most of the time, the following two objects are identical: .PP .Vb 2 \& $cur1 = new Math::Currency 1000.01; \& $cur2 = new Math::Currency "1000.01"; .Ve .PP However, only the second is guaranteed to do what you think it should do. The reason for that lies in how Perl treats bare numbers as opposed to strings. The first \fInew()\fR will receive the Perl-stringified representation of the number 1000.01, whereas the second \fInew()\fR will receive the string \*(L"1000.01\*(R" instead. With most locale settings, this will be largely identical. However, with many European locales (like fr_FR), the first \fInew()\fR will receive the string \&\*(L"1 000,01\*(R" and this will cause Math::BigFloat to report this as \s-1NAN\s0 (Not A Number) because of the odd posix driven formatting. .PP For this reason, it is always recommended that input values be quoted at all times, even if your \s-1POSIX\s0 locale does not have this unfortunate side effect. .SH "Output Formatting" .IX Header "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 \s-1US\s0 standards if you haven't. You can also specify an output format using one of the predefined Locale formats or your own custom format. .Sh "Predefined Locales" .IX Subsection "Predefined Locales" There are currently four predefined Locale formats: .PP .Vb 4 \& USD = United States dollars (the default if no locale) \& EUR = One possible Euro format (no single standard, yet) \& GBP = British Pounds Sterling \& JPY = Japanese Yen (with extended ASCII currency character) .Ve .PP These currency formats are implemented using subclasses for easy extension (see \*(L"Custom Locales\*(R" for details on creating new subclasses for unsupported locales). In particular, you may want to delete and recreate the \s-1EUR\s0 subclass, since the \s-1EUR\s0 \*(L"standard\*(R" permits the use of decimal and grouping seperators (commas and periods) that vary by country. .PP If you want to use any locale other than your default, there are two different ways to specify which currency format you wish to use, with somewhat subtle differences: .IP "* Additional parameter to \fInew()\fR" 4 .IX Item "Additional parameter to new()" If you need a single currency of a different type than the others in your program, use this mode: .Sp .Vb 3 \& use Math::Currency; \& my $dollars = Math::Currency->new("1.23"); # default behavior \& my $euros = Math::Currency->new("1.23", "EUR"); # different format .Ve .Sp The last line above will automatically load the applicable subclass and use that formatting for that specific object. These formats can either use a pre-generated subclass or will automatically generate an automatic \&\*(L"custom subclass\*(R". .IP "* Directly calling the subclass" 4 .IX Item "Directly calling the subclass" If all (or most) of your currency values should be formatted using the same rules, create the objects directly using the subclass: .Sp .Vb 3 \& use Math::Currency::JPY; # Japanese Yen \& my $yen = Math::Currency::JPY->new("1.345"); \& my $yen2 = $yen->new("3.456"); # you can use an existing object .Ve .Sh "Currency Symbol" .IX Subsection "Currency Symbol" The locale definition includes two different Currency Symbol strings: one is the native character(s), like $ or £ or ¥; the other is the three character string defined by the \s-1ISO4217\s0 specification followed by the normal currency separation character (frequently space). The default behavior is to always display the native \s-1CURRENCY_SYMBOL\s0 unless a global parameter is set: .PP .Vb 1 \& $Math::Currency::use_int = 1; # print the currency symbol text .Ve .PP where the \s-1INT_CURR_SYMBOL\s0 text will used instead. .Sh "Custom Subclass" .IX Subsection "Custom Subclass" The included file, scripts/new_currency, will automatically create a new currency formatting subclass, based on your current locale, or any arbitrary locale supported by your operating system. For most unix-like O/S's, the following command will list the locale files installed: .PP .Vb 1 \& locale -a .Ve .PP and any of those installed locales can [potentially] be used to create a new locale formatting file. .PP It is not \fInecessary\fR to do this, since using the format command to switch to a locale which doesn't already have a subclass defined for it will attempt to generate a locale format on the fly. However, it should be noted that the automated generation method will merely look for the first locales that uses the request \s-1INT_CURR_SYMBOL\s0. There may be several locales which use that same currency symbol, with subtle differences (this is especially true of the \s-1EUR\s0 format), so it is best to pre-generate all of the \s-1POSIX\s0 currency subclasses you expect, based on the locales you wish to support, to utilize when installing this module, instead of relying on the autogeneration methods. .PP To create a new locale formatting subclass, change to the top level build directory for Math::Currency and run the following command: .PP .Vb 1 \& scripts/new_currency [xx_XX] .Ve .PP where xx_XX is the locale name obtained from the `locale \-a` command. This will create a new locale subclass in the lib/Math/Currency/ directory, and this file will be installed when `./Build install` is next run. .PP The new_currency script will function from within the current build directory, and doesn't depend the current version of Math::Currency being already installed, so you can build all of your commonly used locale files and install them at once. .Sh "Global Format" .IX Subsection "Global Format" Global formatting can be changed by setting the package global format like this: .PP .Vb 1 \& Math::Currency->format('USD'); .Ve .Sh "\s-1POSIX\s0 Locale Global Formatting" .IX Subsection "POSIX Locale Global Formatting" In addition to the four predefined formats listed above, you can also use the \s-1POSIX\s0 monetary format for a locale which you are not currently running (e.g. for a web site). You can set the global monetary format in effect at any time by using: .PP .Vb 3 \& use POSIX qw( locale_h ); \& setlocale(LC_ALL,"en_GB"); # some locale alias \& Math::Currency->localize; # reinitialize global format .Ve .PP If you don't want to always have to remember to reinitialize the \s-1POSIX\s0 settings when you switch locales, you can set the global parameter: .PP .Vb 1 \& $Math::Currency::always_init = 1; .Ve .PP and every single time a M::C object is printed, the global \f(CW$FORMAT\fR will be updated to the locale current at that time. This may be a performance hit. It would be better if you followed the first method of manually updating the global format immediately after you reset the locale. .PP \&\s-1NOTE:\s0 This function will reset only the global format and will not have effect on objects created with their own overridden formats, even if they were originally based on the global format. .PP \&\s-1NOTE\s0 2: You must have all the locale files in question already loaded; the list reported by `locale \-a` is not always a reliable judge of what files you might actually have installed. If you try and set a nonexistant locale, or set the same locale as is already active, the module will silently retain the current locale settings. .Sh "Object Formats" .IX Subsection "Object Formats" Any object can have it's own format different from the current global format, like this: .PP .Vb 3 \& $pounds = Math::Currency->new(1000, 'GBP'); \& $dollars = Math::Currency->new(1000); # inherits default US format \& $dollars->format( 'USD' ); # explicit object format .Ve .Sh "Format Parameters" .IX Subsection "Format Parameters" The format must contains all of the commonly configured \s-1LC_MONETARY\s0 Locale settings. For example, these are the values of the default \s-1US\s0 format (with comments): { \s-1INT_CURR_SYMBOL\s0 => '\s-1USD\s0', # \s-1ISO\s0 currency text \s-1CURRENCY_SYMBOL\s0 => '$', # Local currency character \s-1MON_DECIMAL_POINT\s0 => '.', # Decimal seperator \s-1MON_THOUSANDS_SEP\s0 => ',', # Thousands seperator \s-1MON_GROUPING\s0 => '3', # Grouping digits \s-1POSITIVE_SIGN\s0 => '', # Local positive sign \s-1NEGATIVE_SIGN\s0 => '\-', # Local negative sign \s-1INT_FRAC_DIGITS\s0 => '2', # Default Intl. precision \s-1FRAC_DIGITS\s0 => '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 N_SIGN_POSN => '1', # Position of negative sign } .PP See chart below for how the various sign character and location settings interact. .PP 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: .PP .Vb 4 \& $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" .Ve .PP Or you can also set individual elements of the current global format: .PP .Vb 1 \& Math::Currency->format('CURRENCY_SYMBOL',' Bucks'); # global changed .Ve .PP The [\s-1NP\s0]_SIGN_POSN parameter determines how positive and negative signs are displayed. [\s-1NP\s0]_CS_PRECEEDS determines where the currency symbol is shown. [\s-1NP\s0]_SEP_BY_SPACE determines whether the currency symbol cuddles the value or not. The following table shows the relationship between these three parameters: .PP .Vb 2 \& p_sep_by_space \& 0 1 2 .Ve .PP .Vb 5 \& 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$ + .Ve .PP .Vb 5 \& 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 .Ve .PP (the negative variants are similar). .Sh "Additional Object Methods" .IX Subsection "Additional Object Methods" There are times when you would like to take a Math::Currency object and use it with some other module or external agent which doesn't understand the currency formatting. .IP "$m\->as_float \- bare floating point notation without currency formatting" 4 .IX Item "$m->as_float - bare floating point notation without currency formatting" When storing the value into a database, you often need a string which corresponds to the value of the currency as a floating point number, but without the special currency formatting. That is what this object method produces. Be sure and use e.g. \s-1DECIMAL\s0(10,2) in MySQL, to ensure that you don't have any floating point rounding issues going from/to the database. .ie n .IP "$m\->as_int \- bare integer number of ""minimum value""" 4 .el .IP "$m\->as_int \- bare integer number of ``minimum value''" 4 .IX Item "$m->as_int - bare integer number of minimum value" Some \s-1US\s0 credit card gateways require all transactions to be expressed in pennies (because their software isn't running Math::Currency!). This object method returns an integer value that corresponds to the currency value multiplied by 10 to the power of the number of decimal places of precision. Essentially, this expresses the currency amount in the smallest discrete value allowed with that currency, so for currency expressed in dollars, this method returns the same value in pennies. .SH "BUGS" .IX Header "BUGS" Please report any bugs or feature requests to \&\f(CW\*(C`bug\-Math\-Currency@rt.cpan.org\*(C'\fR, or through the web interface at . .SH "AUTHOR" .IX Header "AUTHOR" John Peacock .SH "SEE ALSO" .IX Header "SEE ALSO" .Vb 4 \& perl(1). \& perllocale \& Math::BigFloat \& Math::BigInt .Ve