File Coverage

blib/lib/Lingua/UK/Numbers.pm
Criterion Covered Total %
statement 81 81 100.0
branch 35 40 87.5
condition 19 30 63.3
subroutine 9 9 100.0
pod 2 3 66.6
total 146 163 89.5


line stmt bran cond sub pod time code
1             package Lingua::UK::Numbers;
2              
3 3     3   28122 use strict;
  3         7  
  3         142  
4 3     3   17 use warnings;
  3         4  
  3         103  
5 3     3   39 use v5.10;
  3         15  
  3         147  
6 3     3   2228 use utf8;
  3         31  
  3         14  
7              
8 3     3   112 use Exporter;
  3         4  
  3         366  
9             our $VERSION = '0.07';
10             our @ISA = qw(Exporter);
11             our @EXPORT_OK = qw(uah_in_words number_in_words);
12              
13 3     3   22 use Carp;
  3         4  
  3         4706  
14              
15             my %diw = (
16             0 => {
17             0 => { 0 => "нуль", 1 => 1},
18             1 => { 0 => "", 1 => 2},
19             2 => { 0 => "", 1 => 3},
20             3 => { 0 => "три", 1 => 0},
21             4 => { 0 => "чотири", 1 => 0},
22             5 => { 0 => "п'ять", 1 => 1},
23             6 => { 0 => "шість", 1 => 1},
24             7 => { 0 => "сім", 1 => 1},
25             8 => { 0 => "вісім", 1 => 1},
26             9 => { 0 => "дев'ять", 1 => 1},
27             10 => { 0 => "десять", 1 => 1},
28             11 => { 0 => "одинадцять", 1 => 1},
29             12 => { 0 => "дванадцять", 1 => 1},
30             13 => { 0 => "тринадцять", 1 => 1},
31             14 => { 0 => "чотирнадцять", 1 => 1},
32             15 => { 0 => "п'ятнадцять", 1 => 1},
33             16 => { 0 => "шістнадцять", 1 => 1},
34             17 => { 0 => "сімнадцять", 1 => 1},
35             18 => { 0 => "вісімнадцять", 1 => 1},
36             19 => { 0 => "дев'ятнадцять", 1 => 1},
37             },
38             1 => {
39             2 => { 0 => "двадцять", 1 => 1},
40             3 => { 0 => "тридцять", 1 => 1},
41             4 => { 0 => "сорок", 1 => 1},
42             5 => { 0 => "п'ятдесят", 1 => 1},
43             6 => { 0 => "шістдесят", 1 => 1},
44             7 => { 0 => "сімдесят", 1 => 1},
45             8 => { 0 => "вісімдесят", 1 => 1},
46             9 => { 0 => "дев'яносто", 1 => 1},
47             },
48             2 => {
49             1 => { 0 => "сто", 1 => 1},
50             2 => { 0 => "двісті", 1 => 1},
51             3 => { 0 => "триста", 1 => 1},
52             4 => { 0 => "чотириста", 1 => 1},
53             5 => { 0 => "п'ятсот", 1 => 1},
54             6 => { 0 => "шістсот", 1 => 1},
55             7 => { 0 => "сімсот", 1 => 1},
56             8 => { 0 => "вісімсот", 1 => 1},
57             9 => { 0 => "дев`ятсот", 1 => 1}
58             }
59             );
60              
61             my %nom = (
62             0 => {0 => "копійки", 1 => "копійок", 2 => "одна копійка", 3 => "дві копійки"},
63             1 => {0 => "гривні", 1 => "гривень", 2 => "одна гривня", 3 => "дві гривні"},
64             2 => {0 => "тисячі", 1 => "тисяч", 2 => "одна тисяча", 3 => "дві тисячі"},
65             3 => {0 => "мільйона", 1 => "мільйонів", 2 => "один мільйон", 3 => "два мільйони"},
66             4 => {0 => "мільярди", 1 => "мільярдів", 2 => "один мільярд", 3 => "два мільярди"},
67             5 => {0 => "трильйон", 1 => "трильйонів", 2 => "один трильйон", 3 => "два трильйони"}
68             );
69              
70             my $out_hrn;
71              
72             sub uah_in_words {
73 5     5 1 2144 my $sum = shift;
74 5 100       20 return "нуль гривень нуль копійок" if $sum == 0;
75              
76 4         5 my ( $retval, $i, $sum_hrn, $sum_kop );
77              
78 4         5 $retval = "";
79 4 50       8 $out_hrn = ( $sum >= 1 ) ? 0 : 1;
80 4         37 $sum_hrn = sprintf( "%0.0f", $sum );
81 4 100       15 $sum_hrn-- if ( ( $sum_hrn - $sum ) > 0 );
82 4         16 $sum_kop = sprintf( "%0.2f", ( $sum - $sum_hrn ) ) * 100;
83              
84 4         10 my $kop = get_string( $sum_kop, 0 );
85              
86 4   66     17 for ( $i = 1 ; $i < 6 && $sum_hrn >= 1 ; $i++ ) {
87 9         10 my $sum_tmp = $sum_hrn / 1000;
88 9         42 my $sum_part = sprintf( "%0.3f", $sum_tmp - int($sum_tmp) ) * 1000;
89 9         20 $sum_hrn = sprintf( "%0.0f", $sum_tmp );
90              
91 9 100       20 $sum_hrn-- if ( $sum_hrn - $sum_tmp > 0 );
92 9         11 $retval = get_string( $sum_part, $i ) . " " . $retval;
93             }
94 4 100       13 $retval .= " гривень" if ( $out_hrn == 0 );
95 4         6 $retval .= " " . $kop;
96 4         43 $retval =~ s/\s+/ /g;
97 4         14 return $retval;
98             }
99              
100             sub number_in_words {
101 10     10 1 5052 my ( $sum, $gender ) = @_;
102 10 50 66     43 croak 'gender should be "FEMININE" or "MASCULINE"' if $gender ne 'FEMININE' && $gender ne 'MASCULINE';
103              
104 10 100       27 return "нуль" if $sum == 0;
105              
106 8 100       55 local $nom{1} = {
    100          
107             0 => "",
108             1 => "",
109             2 => $gender eq 'FEMININE' ? 'одна': 'один',
110             3 => $gender eq 'FEMININE' ? 'дві': 'два'
111             };
112              
113 8         9 my ( $retval, $i, $sum_words );
114              
115 8         11 $retval = "";
116              
117 8         69 $sum_words = sprintf( "%0.0f", $sum );
118 8 50       25 $sum_words-- if ( ( $sum_words - $sum ) > 0 );
119              
120 8   66     40 for ( $i = 1 ; $i < 6 && $sum_words >= 1 ; $i++ ) {
121 18         25 my $sum_tmp = $sum_words / 1000;
122 18         84 my $sum_part = sprintf( "%0.3f", $sum_tmp - int($sum_tmp) ) * 1000;
123 18         44 $sum_words = sprintf( "%0.0f", $sum_tmp );
124              
125 18 100       39 $sum_words-- if ( $sum_words - $sum_tmp > 0 );
126 18         33 $retval = get_string( $sum_part, $i ) . " " . $retval;
127             }
128              
129 8         40 $retval =~ s/\s+/ /g;
130 8         32 $retval =~ s/\s+$//g;
131              
132 8         41 return $retval;;
133             }
134              
135             sub get_string {
136 31     31 0 40 my ( $sum, $nominal ) = @_;
137 31         38 my ( $retval, $nom ) = ( '', -1 );
138              
139 31 50 66     312 if ( ( $nominal == 0 && $sum < 100 ) || ( $nominal > 0 && $nominal < 6 && $sum < 1000 ) ) {
      33        
      33        
      66        
140 31         37 my $s2 = int( $sum / 100 );
141 31 100       43 if ( $s2 > 0 ) {
142 12         56 $retval .= " " . $diw{2}{$s2}{0};
143 12         17 $nom = $diw{2}{$s2}{1};
144             }
145 31         95 my $sx = sprintf( "%0.0f", $sum - $s2 * 100 );
146 31 50       60 $sx-- if ( $sx - ( $sum - $s2 * 100 ) > 0 );
147              
148 31 100 100     165 if ( ( $sx < 20 && $sx > 0 ) || ( $sx == 0 && $nominal == 0 ) ) {
      66        
      66        
149 12         35 $retval .= " " . $diw{0}{$sx}{0};
150 12         23 $nom = $diw{0}{$sx}{1};
151             } else {
152 19         43 my $s1 = sprintf( "%0.0f", $sx / 10 );
153 19 100       45 $s1-- if ( ( $s1 - $sx / 10 ) > 0 );
154 19         26 my $s0 = int( $sum - $s2 * 100 - $s1 * 10 + 0.5 );
155 19 100       31 if ( $s1 > 0 ) {
156 10         26 $retval .= " " . $diw{1}{$s1}{0};
157 10         13 $nom = $diw{1}{$s1}{1};
158             }
159 19 100       454 if ( $s0 > 0 ) {
160 10         25 $retval .= " " . $diw{0}{$s0}{0};
161 10         595 $nom = $diw{0}{$s0}{1};
162             }
163             }
164             }
165 31 100       52 if ( $nom >= 0 ) {
166 22         57 $retval .= " " . $nom{$nominal}{$nom};
167 22 100       39 $out_hrn = 1 if ( $nominal == 1 );
168             }
169 31         133 $retval =~ s/^\s*//g;
170 31         142 $retval =~ s/\s*$//g;
171              
172 31         151 return $retval;
173             }
174              
175             =head1 NAME
176              
177             Lingua::UK::Numbers - Converts numbers to money sum in words (in Ukrainian hryvnas)
178              
179             =head1 SYNOPSIS
180              
181             use Lingua::UK::Numbers qw(number_in_words uah_in_words);
182              
183             print number_in_words(100);
184              
185             print uah_in_words(1.01);
186              
187              
188             =head1 DESCRIPTION
189              
190             B helps you to convert number to words.
191              
192             =head1 FUNCTIONS
193              
194             =head2 number_in_words( $NUMBER, $GENDER )
195              
196             returns number in words in ukrainian (UTF-8)
197              
198             $GENDER can be 'MASCULINE' or 'FEMININE'
199              
200             =head2 uah_in_words( $NUMBER )
201              
202             returns money sum in ukrainian words(UTF-8)
203              
204             e.g.: 1.01 converted to I, 2.22 converted to I.
205              
206             =head1 AUTHOR
207              
208             Viktor Turskyi
209              
210             =head1 BUGS
211              
212             Please report any bugs or feature requests to Github L
213              
214             =head1 SEE ALSO
215              
216             L
217              
218             =cut
219              
220             1; # End of Lingua::UK::Numbers