package Lingua::NL::Numbers;
$VERSION = '1.3';
use strict;
my $numbers = {
0 => 'nul',
1 => 'een',
2 => 'twee',
3 => 'drie',
4 => 'vier',
5 => 'vijf',
6 => 'zes',
7 => 'zeven',
8 => 'acht',
9 => 'negen',
10 => 'tien',
11 => 'elf',
12 => 'twaalf',
13 => 'dertien',
14 => 'veertien',
15 => 'vijftien',
16 => 'zestien',
17 => 'zeventien',
18 => 'achtien',
19 => 'negentien',
20 => 'twintig',
30 => 'dertig',
40 => 'veertig',
50 => 'vijftig',
60 => 'zestig',
70 => 'zeventig',
80 => 'tachtig',
90 => 'negentig',
};
sub new
{
my $class = shift;
my $number = shift || '';
my $self = {};
bless $self, $class;
if( $number =~ /\d+/ ) {
return( $self->parse($number) );
};
return( $self );
};
sub parse
{
my $self = shift;
my $number = shift;
my $digits;
my $ret = '';
if( defined($numbers->{$number}) ) {
$ret = $numbers->{$number};
}
else {
my $ret_array = [];
@{$digits} = reverse( split('', $number) );
# tens of billions
if( defined($digits->[10]) && ($digits->[10] != 0) ) {
my $temp = $self->_formatTens( $digits->[9], $digits->[10] );
unshift @{$ret_array}, "$temp biljoen";
}
elsif( defined($digits->[9]) && ($digits->[9] != 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[9], ' biljoen' );
};
# hundreds of millions
if( defined($digits->[8]) && ($digits->[8] != 0) ) {
if( ($digits->[7] == 0) && ($digits->[6] == 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[8], ' honderd miljard' );
}
else {
unshift @{$ret_array}, $self->_formatLarge( $digits->[8], ' honderd' );
};
};
# tens of millions
if( defined($digits->[7]) && ($digits->[7] != 0) ) {
my $temp = $self->_formatTens( $digits->[6], $digits->[7] );
unshift @{$ret_array}, "$temp miljard";
}
elsif( defined($digits->[6]) && ($digits->[6] != 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[6], ' miljard' );
};
# hundreds of thousands
if( defined($digits->[5]) && ($digits->[5] != 0) ) {
if( ($digits->[4] == 0) && ($digits->[3] == 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[5], ' honderd duizend' );
}
else {
unshift @{$ret_array}, $self->_formatLarge( $digits->[5], ' honderd' );
};
};
# tens of thousands
if( defined($digits->[4]) && ($digits->[4] != 0) ) {
my $temp = $self->_formatTens( $digits->[3], $digits->[4] );
unshift @{$ret_array}, "$temp duizend";
}
elsif( defined($digits->[3]) && ($digits->[3] == 1) ) {
unshift @{$ret_array}, ' duizend';
}
elsif( defined($digits->[3]) && ($digits->[3] != 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[3], ' duizend' );
};
# hundreds
if( defined($digits->[2]) && ($digits->[2] == 1) ) {
unshift @{$ret_array}, 'honderd';
}
elsif( defined($digits->[2]) && ($digits->[2] != 0) ) {
unshift @{$ret_array}, $self->_formatLarge( $digits->[2], 'honderd' );
};
# tens
unshift @{$ret_array}, $self->_formatTens( $digits->[0], $digits->[1], 'en' );
$ret = $self->_sortReturn( $ret_array, $digits );
};
return( $ret );
};
sub _sortReturn
{
my $self = shift;
my $ret_array = shift;
my $digits = shift;
my $large_nums = 0;
my $ret = '';
my $size = @{$ret_array};
if( $size == 1 ) {
return( $ret_array->[0] );
}
elsif( $size > 1 ) {
$large_nums = 1;
};
for( my $i = $size; $i > 0; $i-- ) {
if( defined($ret_array->[$i]) ) {
if( $ret_array->[$i] =~ /(miljard|duizend)/ ) {
$ret .= $ret_array->[$i] .', ';
}
else {
$ret .= $ret_array->[$i] .' ';
};
};
};
if( ($digits->[0] == 0) && ($digits->[1] == 0) ) {
# do nothing
}
elsif( ($digits->[0] == 0) || ($digits->[1] == 0) || ($digits->[1] == 1) ) {
if( $large_nums ) {
$ret .= ' en ';
};
$ret .= $ret_array->[0];
}
else {
$ret .= ' '. $ret_array->[0];
};
$ret =~ s/(^ |\s{2,}| $)/ /g;
return( $ret );
};
sub _formatTens
{
my $self = shift;
my $units = shift;
my $tens = shift;
my $en = shift || ' en ';
# Both digits are zero
unless( $units || $tens ) {
return;
};
if( $tens == 0 ) {
return( $numbers->{$units} );
}
elsif( ($tens == 1) || ($units == 0) ) {
my $temp = $tens . $units;
return( $numbers->{$temp} );
};
my $temp = $tens . 0;
return( $numbers->{$units} . $en . $numbers->{$temp} );
};
sub _formatLarge
{
my $self = shift;
my $digit = shift;
my $word = shift;
my $ret = "$numbers->{$digit}$word";
return( $ret );
};
1;
=pod
=head1 NAME
Lingua::NL::Numbers - Perl module for converting numeric values into their Dutch equivalents
=head1 DESCRIPTION
Initial release, documentation and updates will follow.
=head1 SYNOPSIS
use Lingua::NL::Numbers;
my $numbers = Lingua::NL::Numbers->new;
my $text = $numbers->parse( 123 );
# prints 'een honderd, drie en twintig'
print $text;
=head1 KNOWN BUGS
None, but that does not mean there are not any.
=head1 AUTHOR
Alistair Francis, http://search.cpan.org/~friffin/
=cut