Acme-Numbers
view release on metacpan or search on metacpan
lib/Acme/Numbers.pm view on Meta::CPAN
Inspired by this post
http://beautifulcode.oreillynet.com/2007/12/the_cardinality_of_a_fluent_in.php
and a burning curiosity. At leats, I hope the burning
was curiosity.
=head1 ONE BIIIIIIIIIIIILLION
By default billion is 10**12 because, dammit, that's right.
If you want it to be an American billion then do
use Acme::Numbers billion => 10**9;
Setting this automatically changes all the larger numbers
(trillion, quadrillion, etc) to match.
=head1 METHODS
You should never really use these methods on the class directly.
All numbers handled by C<Lingua::EN::Words2Nums> are handled by this module.
In addition ...
=cut
sub import {
my $class = shift;
my %opts = @_;
$opts{billion} = 10**12 unless defined $opts{billion};
no strict 'refs';
no warnings 'redefine';
my ($pkg, $file) = caller;
$Lingua::EN::Words2Nums::billion = $opts{billion};
foreach my $num ((keys %Lingua::EN::Words2Nums::nametosub,
'and', 'point', 'zero',
'pound', 'pounds', 'pence', 'p',
'dollars', 'cents'))
{
*{"$pkg\::$num"} = sub { $class->$num };
}
};
=head2 new <value> <operator>
C<operator> can be 'num', 'and' or 'point'
=cut
sub new {
my $class = shift;
$class = ref $class if ref $class;
my $val = shift;
my $op = shift;
my $name = shift || $op;
bless { value => $val, operator => $op, name => $name }, $class;
}
=head2 name
The name of this object (i.e the method that was originally called).
=cut
sub name {
return $_[0]->{name};
}
=head2 value
The current numeric value
=cut
sub value {
my $self = shift;
my $val = $self->{value};
# if we're 'pence' then divide by 100 and then pretend we're pounds
if ($self->{operator} =~ m!^p(ence)?$!) {
# this fixes something where there's 0
# pounds and a trailing zero like 0.50
$self->{last_added} = $val;
$val = $val/100;
$self->{operator} = 'pounds';
}
if ($self->{operator} =~ m!^pounds?$!) {
my ($num, $frac) = split /\./, $val;
$frac ||= 0;
# this also fixes 0 pounds trailing zero
$frac = $self->{last_added} if defined $self->{last_added} && $self->{last_added}>$frac;
# we substr to fix one.pound.fifty.pence which
# leaves $frac as '500'
$val = sprintf("%d.%02d",$num,substr($frac,0,2));
}
return $val;
}
sub AUTOLOAD {
my $self = shift;
my $method = $AUTOLOAD;
$method =~ s/.*://; # strip fully-qualified portion
my $val;
# nasty override - we should probably have a
# generic major or minor currency indicator
# if we could store and propogate the currency
# then we could also throw errors at mismatched
# units e.g five.pounds.and.fifty.cents
# but maybe also print out the correct sigil
# e.g $5.50
$method = 'pounds' if $method eq 'dollars';
$method = 'pence' if $method eq 'cents';
# dummy methods
if ($method eq 'and' || $method =~ m!^p!) {
$val = $self->new(0, $method)
( run in 0.906 second using v1.01-cache-2.11-cpan-39bf76dae61 )