File Coverage

blib/lib/Math/BigInt/Named/Norwegian.pm
Criterion Covered Total %
statement 76 76 100.0
branch 34 36 94.4
condition 13 15 86.6
subroutine 6 6 100.0
pod 1 1 100.0
total 130 134 97.0


line stmt bran cond sub pod time code
1             #!perl
2              
3             package Math::BigInt::Named::Norwegian;
4              
5 2     2   14 use strict;
  2         18  
  2         64  
6 2     2   10 use warnings;
  2         4  
  2         78  
7              
8 2     2   13 use Math::BigInt::Named;
  2         4  
  2         17  
9             our @ISA = qw< Math::BigInt::Named >;
10              
11             our $VERSION = '0.07';
12              
13             my $SMALL = [ qw/
14             null
15             en
16             to
17             tre
18             fire
19             fem
20             seks
21             syv
22             åtte
23             ni
24             ti
25             elleve
26             tolv
27             tretten
28             fjorten
29             femten
30             seksten
31             sytten
32             atten
33             nitten
34             / ];
35              
36             my $TENS = [ qw /
37             ti
38             tjue
39             tretti
40             førti
41             femti
42             seksti
43             sytti
44             åtti
45             nitti
46             / ];
47              
48             my $HUNDREDS = [ qw /
49             en
50             to
51             tre
52             fire
53             fem
54             seks
55             sju
56             åtte
57             ni
58             / ];
59              
60             my $TRIPLE = [ qw /
61             mi
62             bi
63             tri
64             kvadri
65             kvinti
66             seksti
67             septi
68             okti
69             noni
70             desi
71             undesi
72             duodesi
73             tredesi
74             kvattordesi
75             kvindesi
76             seksdesi
77             septendesi
78             oktodesi
79             novemdesi
80             viginti
81             / ];
82              
83             sub name {
84 55     55 1 99 my $x = shift;
85 55 50       135 $x = Math::BigInt -> new($x) unless ref($x);
86              
87 55         96 my $class = ref($x);
88              
89 55 50       128 return '' if $x -> is_nan();
90              
91 55         320 my $ret = '';
92 55         124 my $y = $x -> copy();
93 55         1072 my $rem;
94              
95 55 100       128 if ($y -> sign() eq '-') {
96 1         7 $ret = 'minus ';
97 1         7 $y -> babs();
98             }
99              
100 55 100       405 if ($y < 1000) {
101 42         5144 return $ret . $class -> _triple($y, 1, 0);
102             }
103              
104             # Split the number into numerical triplets.
105              
106 13         1431 my @num = ();
107 13         36 while (!$y -> is_zero()) {
108 32         405 ($y, $rem) = $y -> bdiv(1000);
109 32         7160 unshift @num, $rem;
110             }
111              
112             # Convert each numerical triplet into a string.
113              
114 13         156 my @str = ();
115 13         39 for my $i (0 .. $#num) {
116 32         50 my $num = $num[$i];
117 32         49 my $str;
118 32         54 my $index = $#num - $i;
119              
120 32         46 my $count;
121 32 100 100     76 if ($num == 1 && $index == 1) {
122 8         842 $count = "ett"; # "ett tusen", not "en tusen"
123             } else {
124 24         2463 $count = $class -> _triple($num, 0, $i);
125             }
126 32         1307 $str .= $count;
127              
128             # "tusen", "million"/"millioner", "milliard/milliarder", ...
129              
130 32 100       70 if ($index > 0) {
131 19         55 my $triple_name = $class -> _triple_name($#num - $i, $num);
132 19         100 $str .= ' ' . $triple_name;
133             }
134              
135 32         75 $str[$i] = $str;
136             }
137              
138             # 1100 -> "ett tusen ett hundre" (not "ett tusen og ett hundre")
139             # 1099 -> "ett tusen og nittini" (not "ett tusen nittini")
140             # 1098 -> "ett tusen og nittiåtte" (not "ett tusen nittiåtte")
141             # ...
142             # 1001 -> "ett tusen og en" (not "ett tusen en")
143             # 1000 -> "ett tusen" (not "ett tusen og null"
144              
145 13 100 66     51 if (@num > 1 && 0 < $num[-1] && $num[-1] < 100) {
      100        
146 5         1116 splice @str, -1, 0, "og";
147             }
148              
149 13         1624 $ret . join(" ", grep /\S/, @str);
150             }
151              
152             sub _triple_name {
153 19     19   37 my ($self, $index, $number) = @_;
154             # index => 0 hundreds, tens and ones
155             # index => 1 thousands
156             # index => 2 millions
157              
158 19 100 66     58 return '' if $index == 0 || $number -> is_zero();
159 14 100       189 return 'tusen' if $index == 1;
160              
161 6         10 my $postfix = 'llion';
162 6         10 my $plural = 'er';
163 6 100       18 if (($index & 1) == 1) {
164 1         3 $postfix = 'lliard';
165             }
166 6 100       21 $postfix .= $plural unless $number -> is_one();
167 6         83 $index -= 2;
168 6         17 $TRIPLE -> [$index >> 1] . $postfix;
169             }
170              
171             sub _triple {
172             # return name of a triple
173             # input: number >= 0, < 1000
174             # only true if triple is the only triple
175 66     66   140 my ($self, $number, $only) = @_;
176              
177             # 0 => null, but only if there is just one triple
178 66 100 100     150 return '' if $number -> is_zero() && !$only;
179              
180             # we have the full name for these
181 58 100       787 return $SMALL -> [$number] if $number <= $#$SMALL;
182              
183             # New code:
184              
185 29         2934 my @num = ();
186 29         79 $num[1] = $number % 100; # tens and ones
187 29         5189 $num[0] = ($number - $num[1]) / 100; # hundreds
188              
189 29         8843 my @str = ();
190              
191             # Do the hundreds, if any.
192              
193 29 100       87 if ($num[0]) {
194 17         397 my $str;
195 17 100       42 $str = $num[0] == 1 ? "ett" # "ett hundre", not "en hundre"
196             : $HUNDREDS -> [$num[0] - 1];
197 17         3856 $str .= " hundre";
198 17         42 push @str, $str;
199             }
200              
201             # Do the tens and ones, if any.
202              
203 29 100       345 if ($num[1]) {
204 18         395 my $str;
205 18         41 my $ones = $num[1] % 10;
206 18         3153 my $tens = ($num[1] - $ones) / 10;
207 18 100       5592 if ($num[1] <= $#$SMALL) {
208 4         436 $str = $SMALL -> [ $num[1] ];
209             } else {
210 14         1450 $str = $TENS -> [ $tens - 1];
211 14 100       2951 if ($ones > 0) {
212 13         2078 $str .= "";
213 13         37 $str .= $SMALL -> [ $ones ];
214             }
215             }
216 18         623 push @str, $str;
217             }
218              
219 29         484 return join " og ", @str;
220             }
221              
222             1;
223              
224             __END__