File Coverage

blib/lib/Lingua/HU/Numbers.pm
Criterion Covered Total %
statement 94 94 100.0
branch 67 70 95.7
condition 18 24 75.0
subroutine 11 11 100.0
pod 2 2 100.0
total 192 201 95.5


line stmt bran cond sub pod time code
1             package Lingua::HU::Numbers;
2              
3 2     2   23042 use 5.006;
  2         8  
  2         88  
4              
5 2     2   12 use warnings;
  2         3  
  2         61  
6 2     2   10 use strict;
  2         8  
  2         78  
7              
8 2     2   11 use Carp;
  2         4  
  2         160  
9 2     2   2236 use utf8;
  2         26  
  2         10  
10              
11             require Exporter;
12             our @ISA = qw(Exporter);
13             our @EXPORT = ();
14             our @EXPORT_OK = qw(num2hu num2hu_ordinal);
15              
16             our $VERSION = '0.07';
17              
18             my %dig;
19              
20             @dig{ 0..30,40,50,60,70,80,90 } = qw( nulla egy kettő három négy öt hat hét
21             nyolc kilenc tíz tizenegy tizenkettő tizenhárom tizennégy tizenöt tizenhat
22             tizenhét tizennyolc tizenkilenc húsz huszonegy huszonkettő huszonhárom
23             huszonnégy huszonöt huszonhat huszonhét huszonnyolc huszonkilenc harminc
24             negyven ötven hatvan hetven nyolcvan kilencven );
25              
26             my %ord;
27              
28             my @tenord = qw ( egyedik kettedik harmadik negyedik ötödik hatodik hetedik
29             nyolcadik kilencedik);
30              
31             my %tenord; @tenord{ 1..9 } = @tenord;
32              
33             my $empty = q{};
34             my $minus = q{-};
35             my $space = q{ };
36              
37             my @desc = ($empty,qw(ezer millió milliárd billió billiárd trillió trilliárd
38             kvadrillió kvadrilliárd kvintillió kvintilliárd szextillió szextilliárd
39             szeptillió szeptilliárd oktillió oktilliárd nonillió nonilliárd
40             decillió decilliárd));
41              
42             my @frac = ($empty,qw( ezred milliomod milliárdod billiomod billiárdod
43             trilliomod trilliárdod kvadrilliomod kvadrilliárdod kvintilliomod
44             kvintilliárdod szextilliomod szextilliárdod szeptilliomod szeptilliárdod
45             oktilliomod oktilliárdod nonilliomod nonilliárdod decilliomod
46             decilliárdod ));
47            
48             @ord{ 0..10,11..19,20,21..29,30,40,50,60,70,80,90,100 } = (qw(nulladik első
49             második), @tenord[2..8], 'tizedik',(map { "tizen$_" } @tenord), 'huszadik',
50             (map { "huszon$_" } @tenord), qw( harmincadik negyvenedik ötvenedik hatvanadik
51             hetvenedik nyolcvanadik kilencvenedik századik));
52              
53             sub num2hu {
54 31     31 1 1609 my $num = $_[0];
55 31 100       113 return $dig{'0'} if ($num =~ m/^[+-]0+$/sx);
56 29 50 33     159 return unless defined $num && length $num;
57 29 100       651 croak('Number is not properly formatted!')
58             if ($num !~ m/^[+-]?\d+(\.\d+)?$/sx);
59 26         119 my ($int,$frac) = $num =~ m/^[+-]?(\d+)(?:\.(\d+))?$/x;
60 26 100 100     371 croak('The number is too large, the module can\'t handle it!')
      66        
      66        
61             if ($int && length($int) > 66 || $frac && length($frac) > 66);
62 25         35 my $plusmin = $empty;
63 25         69 $num =~ s/^([+-])/$plusmin = $1;$empty/esx;
  6         15  
  6         19  
64 25 100       69 $plusmin = ($plusmin eq $minus) ? 'mínusz ':$empty;
65 25 100       80 if ($num =~ m/(\d+)\.(\d+)/x) {
66 9 100       20 if (_frac2hu($2)) { return $plusmin._int2hu($1).' egész '._frac2hu($2)
  7         16  
67 2         6 } else { return $plusmin._int2hu($1); }
68             } else {
69 16         33 return $plusmin._int2hu($num);
70             }
71             }
72              
73             sub num2hu_ordinal {
74 21     21 1 1602 my $num = $_[0];
75 21 50 33     128 return unless defined $num && length($num);
76 21 100       512 croak('You need to specify a positive integer for this function!')
77             if ($num !~ m/^\d+$/sx);
78 19 100       220 croak('The number is too large, the module can\'t handle it!')
79             if (length($num) > 66);
80 18 100       53 return $ord{'0'} if ($num =~ m/^0+$/sx);
81 17         35 return _ord2hu($num);
82             }
83              
84             sub _int2hu {
85 101     101   149 my $num = $_[0];
86 101         131 my $recur = $_[1];
87 101 100       595 return $dig{$num} if ($dig{$num});
88 49         65 my ($hun,$end,$pre);
89 49 100 100     342 if ($num =~ m/^(\d)(\d)$/x) {
    100          
    100          
    100          
90 6         68 return $dig{$1.'0'} . $dig{$2}
91             } elsif ($num =~ m/^(\d)(\d\d)$/x) {
92 22         55 ($hun,$end) = ($1,$2);
93 22 100 100     110 $hun = ($hun eq '1' && !$recur)? 'száz':"$dig{$hun}száz";
94 22 100       108 return $hun if ($end eq '00');
95 13         46 return $hun._int2hu($2 + 0);
96             } elsif ($num <= 2000 && $num =~ m/^1(\d\d\d)$/x) {
97 5 100       34 return 'ezer' if ($1 eq '000');
98 3         12 return 'ezer'._int2hu($1 + 0,1);
99             } elsif ($num =~ m/^(\d{1,3})((?:000){1,2})$/x) {
100 8 100       45 ($pre,$end) = ($1,(length($2) == 3)? $desc[1]:$desc[2]);
101 8         27 return _int2hu($pre + 0).$end;
102             } else {
103 8         21 return _bigint2hu($num);
104             }
105              
106             }
107              
108             sub _bigint2hu {
109 8     8   15 my $num = $_[0];
110 8         11 my @parts;
111 8         11 my $count = 0;
112 8         8 my $part;
113 8 100       25 if ($num =~ m/001(\d{3})$/x) {
114 1         5 $num =~ s/00(1\d{3})$//x;
115 1         5 $part = $1;
116 1         3 unshift @parts, [ $part, $count ];
117 1         3 $count += 2;
118             }
119 8         48 while ($num =~ s/(\d{1,3})$//x) {
120 35         78 $part = $1 + 0;
121 35 100       96 unshift @parts, [ $part, $count ] if ($part);
122 35         193 $count++;
123             }
124 8         11 my @out;
125 8         24 for (0..$#parts) {
126 15 100       38 push @out, _int2hu($parts[$_]->[0],$_).
127             (($parts[$_]->[1] > 8)? $space:$empty).
128             $desc[$parts[$_]->[1]];
129             }
130 8         77 return join($minus,@out);
131            
132             }
133              
134             sub _frac2hu {
135 16     16   33 my $num = $_[0];
136 16         57 $num =~ s/0+$//x;
137 16         29 my $place = length($num);
138 16         31 $num =~ s/^0+//x;
139 16 100       45 return if ($num eq $empty);
140 14 100       28 if ($place < 3) {
141 8 100       19 $place = ($place == 1) ? 'tized':'század';
142 8         17 return _int2hu($num).$space.$place;
143             } else {
144 6         10 my $rest = $empty;
145 6 100       27 $rest = _int2hu('1'.('0' x ($place % 3))) if ($place % 3);
146 6         16 $place = int( $place / 3 );
147 6         13 return _int2hu($num).$space.$rest.$frac[$place];
148             }
149              
150              
151             }
152              
153             sub _ord2hu {
154 27     27   48 my $num = $_[0];
155 27         42 $num =~ s/^0+//x;
156 27 100       100 return $ord{$num} if $ord{$num};
157 21 100       153 if ($num =~ m/^(\d)(\d)$/x) {
    100          
    100          
    100          
    50          
158 5         20 return _int2hu($1.'0').$tenord{$2};
159             } elsif ($num =~ m/^(\d)(\d\d)$/x) {
160 6 100       23 if ($2 eq '00') { return _int2hu($1.'00').'adik' }
  1         5  
161 5         21 else { return _int2hu($1.'00')._ord2hu($2); }
162             } elsif ($num =~ m/^(\d+?)((?:000)+)$/x) {
163 5 100 100     31 if ($1 eq '1' && $2 eq '000') { return 'ezredik' }
  1         7  
164 4         10 else { return _int2hu($1).$frac[(length($2) / 3)].'ik'; }
165             } elsif ($num =~ m/^1(\d\d\d)$/x) {
166 1         4 return 'ezer'._ord2hu($1);
167             } elsif ($num =~ m/^(\d+)(\d\d\d)$/x) {
168 4         20 return _int2hu($1.'000').$minus._ord2hu($2);
169             }
170            
171             }
172             1;
173             __END__