line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# For Emacs: -*- mode:cperl; mode:folding; coding:utf-8; -*- |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# (c) 2003-2010 PetaMem, s.r.o. |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Lingua::ZHO::Numbers; |
7
|
|
|
|
|
|
|
# ABSTRACT: Number 2 word conversion in ZHO. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# {{{ use block |
10
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
22997
|
use 5.10.1; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
12
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
29
|
|
13
|
1
|
|
|
1
|
|
5
|
use Carp; |
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
70
|
|
14
|
1
|
|
|
1
|
|
4
|
use Exporter; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
30
|
|
15
|
1
|
|
|
1
|
|
4
|
use base 'Exporter'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
66
|
|
16
|
1
|
|
|
1
|
|
4
|
use vars qw($Charset $VERSION @EXPORT_OK); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
402
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# }}} |
19
|
|
|
|
|
|
|
# {{{ variables declaration |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
$Lingua::ZHO::Numbers::VERSION = 0.1192; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
@EXPORT_OK = 'number_to_zh'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
$Charset = 'pinyin'; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our %MAP = ( |
28
|
|
|
|
|
|
|
($] >= 5.006) ? eval ## no critic |
29
|
|
|
|
|
|
|
q( |
30
|
|
|
|
|
|
|
'traditional' => { |
31
|
|
|
|
|
|
|
mag => [ '', split(' ', "\x{842c} \x{5104} \x{5146} \x{4eac} \x{5793} \x{79ed} \x{7a70} \x{6e9d} \x{6f97} \x{6b63} \x{8f09} \x{6975} \x{6046}\x{6cb3}\x{6c99} \x{963f}\x{50e7}\x{7947} \x{90a3}\x{7531}\x{4ed6} \x{4e0d}\x{53ef}\x{601d}\x{8b70} \x{7121}\x{91cf}\x{5927}\x{6578}") ], |
32
|
|
|
|
|
|
|
ord => [ '', split(' ', "\x{5341} \x{767e} \x{5343}") ], |
33
|
|
|
|
|
|
|
dig => [ split(' ', "\x{96f6} \x{4e00} \x{4e8c} \x{4e09} \x{56db} \x{4e94} \x{516d} \x{4e03} \x{516b} \x{4e5d} \x{5341}") ], |
34
|
|
|
|
|
|
|
dot => "\x{9ede}", |
35
|
|
|
|
|
|
|
neg => "\x{8ca0}", |
36
|
|
|
|
|
|
|
}, |
37
|
|
|
|
|
|
|
'simplified' => { |
38
|
|
|
|
|
|
|
mag => [ '', split(' ', "\x{4e07} \x{4ebf} \x{5146} \x{4eac} \x{5793} \x{79ed} \x{7a70} \x{6c9f} \x{6da7} \x{6b63} \x{8f7d} \x{6781} \x{6052}\x{6cb3}\x{6c99} \x{963f}\x{50e7}\x{7957} \x{90a3}\x{7531}\x{4ed6} \x{4e0d}\x{53ef}\x{601d}\x{8bae} \x{65e0}\x{91cf}\x{5927}\x{6570}") ], |
39
|
|
|
|
|
|
|
ord => [ '', split(' ', "\x{5341} \x{767e} \x{5343}") ], |
40
|
|
|
|
|
|
|
dig => [ split(' ', "\x{96f6} \x{4e00} \x{4e8c} \x{4e09} \x{56db} \x{4e94} \x{516d} \x{4e03} \x{516b} \x{4e5d} \x{5341}") ], |
41
|
|
|
|
|
|
|
dot => "\x{70b9}", |
42
|
|
|
|
|
|
|
neg => "\x{8d1f}", |
43
|
|
|
|
|
|
|
}, |
44
|
|
|
|
|
|
|
) : (), |
45
|
|
|
|
|
|
|
'big5' => { |
46
|
|
|
|
|
|
|
mag => [ '', split(' ', "\xB8U \xBB\xF5 \xA5\xFC \xA8\xCA \xAB\xB2 \xD2\xF1 \xF6\xF8 \xB7\xBE \xBC\xEE \xA5\xBF \xB8\xFC \xB7\xA5 \xAB\xED\xAAe\xA8F \xAA\xFC\xB9\xAC\xAC\xE9 \xA8\xBA\xA5\xD1\xA5L \xA4\xA3\xA5i\xAB\xE4\xC4\xB3 \xB5L\xB6q\xA4j\xBC\xC6") ], |
47
|
|
|
|
|
|
|
ord => [ '', split(' ', "\xA4Q \xA6\xCA \xA4d") ], |
48
|
|
|
|
|
|
|
dig => [ split(' ', "\xB9s \xA4\@ \xA4G \xA4T \xA5| \xA4\xAD \xA4\xBB \xA4C \xA4K \xA4E \xA4Q") ], |
49
|
|
|
|
|
|
|
dot => "\xC2I", |
50
|
|
|
|
|
|
|
neg => "\xADt", |
51
|
|
|
|
|
|
|
}, |
52
|
|
|
|
|
|
|
'gb' => { |
53
|
|
|
|
|
|
|
mag => [ '', split(' ', "\xCD\xF2 \xD2\xDA \xD5\xD7 \xBE\xA9 \xDB\xF2 \xEF\xF6 \xF0\xA6 \xB9\xB5 \xBD\xA7 \xD5\xFD \xD4\xD8 \xBC\xAB \xBA\xE3\xBA\xD3\xC9\xB3 \xB0\xA2\xC9\xAE\xEC\xF3 \xC4\xC7\xD3\xC9\xCB\xFB \xB2\xBB\xBF\xC9\xCB\xBC\xD2\xE9 \xCE\xDE\xC1\xBF\xB4\xF3\xCA\xFD") ], |
54
|
|
|
|
|
|
|
ord => [ '', split(' ', "\xCA\xAE \xB0\xD9 \xC7\xA7") ], |
55
|
|
|
|
|
|
|
dig => [ split(' ', "\xC1\xE3 \xD2\xBB \xB6\xFE \xC8\xFD \xCB\xC4 \xCE\xE5 \xC1\xF9 \xC6\xDF \xB0\xCB \xBE\xC5 \xCA\xAE") ], |
56
|
|
|
|
|
|
|
dot => "\xB5\xE3", |
57
|
|
|
|
|
|
|
neg => "\xB8\xBA", |
58
|
|
|
|
|
|
|
}, |
59
|
|
|
|
|
|
|
'pinyin' => { |
60
|
|
|
|
|
|
|
mag => [ '', map {$_ } qw( |
61
|
|
|
|
|
|
|
Wan Yi Zhao Jing Gai Zi Rang Gou Jian Zheng Zai Ji |
62
|
|
|
|
|
|
|
HengHeSha AZengZhi NaYouTa BuKeSiYi WuLiangDaShu |
63
|
|
|
|
|
|
|
) ], |
64
|
|
|
|
|
|
|
ord => [ '', map {$_ } qw(Shi Bai Qian) ], |
65
|
|
|
|
|
|
|
dig => [ qw(Ling Yi Er San Si Wu Liu Qi Ba Jiu Shi) ], |
66
|
|
|
|
|
|
|
dot => ' Dian ', |
67
|
|
|
|
|
|
|
neg => 'Fu ', |
68
|
|
|
|
|
|
|
}, |
69
|
|
|
|
|
|
|
); |
70
|
|
|
|
|
|
|
# }}} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# {{{ import |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub import { |
75
|
1
|
|
|
1
|
|
6
|
my ($class, $charset) = @_; |
76
|
1
|
|
|
|
|
2
|
$class->charset($charset); |
77
|
1
|
|
|
|
|
59
|
return $class->export_to_level(1, $class); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# }}} |
81
|
|
|
|
|
|
|
# {{{ charset |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub charset { |
84
|
4
|
|
|
4
|
1
|
2192
|
my ($class, $charset) = @_; |
85
|
|
|
|
|
|
|
|
86
|
1
|
|
|
1
|
|
6
|
no strict 'refs'; ## no critic |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
833
|
|
87
|
4
|
100
|
|
|
|
12
|
return ${"$class\::Charset"} unless defined $charset; |
|
1
|
|
|
|
|
4
|
|
88
|
|
|
|
|
|
|
|
89
|
3
|
50
|
33
|
|
|
20
|
$charset = 'gb' if $charset =~ /^gb/i or $charset =~ /^euc-cn$/i; |
90
|
3
|
100
|
|
|
|
10
|
$charset = 'big5' if $charset =~ /big5/i; |
91
|
3
|
50
|
|
|
|
3
|
return ${"$class\::Charset"} = lc($charset) if exists ${"$class\::MAP"}{lc($charset)}; |
|
3
|
|
|
|
|
10
|
|
|
3
|
|
|
|
|
15
|
|
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# }}} |
95
|
|
|
|
|
|
|
# {{{ map_zho |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub map_zho { |
98
|
0
|
|
|
0
|
1
|
0
|
return \%MAP; |
99
|
|
|
|
|
|
|
} |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# }}} |
102
|
|
|
|
|
|
|
# {{{ new |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub new { |
105
|
0
|
|
|
0
|
1
|
0
|
my ($class, $num) = @_; |
106
|
0
|
|
|
|
|
0
|
bless (\$num, $class); |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# }}} |
110
|
|
|
|
|
|
|
# {{{ parse |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub parse { |
113
|
0
|
|
|
0
|
1
|
0
|
my ($self, $num) = @_; |
114
|
0
|
|
|
|
|
0
|
${$self} = $num; |
|
0
|
|
|
|
|
0
|
|
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# }}} |
118
|
|
|
|
|
|
|
# {{{ get_string |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub get_string { |
121
|
0
|
|
|
0
|
1
|
0
|
my ($self) = @_; |
122
|
0
|
|
|
|
|
0
|
return number_to_zh($$self); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# }}} |
126
|
|
|
|
|
|
|
# {{{ number_to_zh |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub number_to_zh { |
129
|
12
|
|
|
12
|
1
|
2653
|
my @a = @_; |
130
|
12
|
|
|
|
|
37
|
return __PACKAGE__->_convert($MAP{$Charset}, @a); |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
# }}} |
134
|
|
|
|
|
|
|
# {{{ convert |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _convert { |
137
|
12
|
|
|
12
|
|
18
|
my ($class, $map, $input) = @_; |
138
|
|
|
|
|
|
|
|
139
|
12
|
100
|
66
|
|
|
130
|
croak 'You should specify a number from interval [0, trillion)' |
|
|
|
66
|
|
|
|
|
140
|
|
|
|
|
|
|
if !defined $input |
141
|
|
|
|
|
|
|
|| $input !~ m{\A[\-\.\d]+\z}xms |
142
|
|
|
|
|
|
|
|| $input >= 10 ** 15; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
8
|
|
|
|
|
11
|
$input =~ s/[^\d\.\-]//; |
146
|
|
|
|
|
|
|
|
147
|
8
|
|
|
|
|
8
|
my @dig = @{$map->{dig}}; |
|
8
|
|
|
|
|
35
|
|
148
|
8
|
|
|
|
|
10
|
my @ord = @{$map->{ord}}; |
|
8
|
|
|
|
|
20
|
|
149
|
8
|
|
|
|
|
9
|
my @mag = @{$map->{mag}}; |
|
8
|
|
|
|
|
34
|
|
150
|
8
|
|
|
|
|
9
|
my $dot = $map->{dot}; |
151
|
8
|
|
|
|
|
9
|
my $neg = $map->{neg}; |
152
|
|
|
|
|
|
|
|
153
|
8
|
|
|
|
|
8
|
my $out = ''; |
154
|
8
|
|
|
|
|
7
|
my $delta; |
155
|
8
|
50
|
|
|
|
16
|
if ($input =~ s/\.(.*)//) { |
156
|
0
|
|
|
|
|
0
|
$delta = $1; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
8
|
50
|
|
|
|
14
|
$out = $neg if $input =~ s/^\-//; |
160
|
8
|
|
|
|
|
14
|
$input =~ s/^0+//; |
161
|
8
|
|
100
|
|
|
19
|
$input ||= '0'; |
162
|
|
|
|
|
|
|
|
163
|
8
|
|
|
|
|
8
|
my @chunks; |
164
|
8
|
|
|
|
|
73
|
unshift @chunks, $1 while ($input =~ s/(\d{1,4})$//g); |
165
|
8
|
|
|
|
|
11
|
my $mag = $#chunks; |
166
|
8
|
50
|
|
|
|
488
|
my $zero = ($] >= 5.005) ? eval 'qr/$dig[0]$/' : quotemeta($dig[0]) . '$'; ## no critic |
167
|
|
|
|
|
|
|
|
168
|
8
|
|
|
|
|
26
|
foreach my $num (@chunks) { |
169
|
12
|
|
|
|
|
17
|
my $tmp = ''; |
170
|
|
|
|
|
|
|
|
171
|
12
|
|
|
|
|
19
|
for (reverse 0..3) { |
172
|
48
|
|
|
|
|
76
|
my $n = int($num / (10 ** $_)) % 10; |
173
|
48
|
100
|
100
|
|
|
149
|
next unless $tmp or $n; |
174
|
20
|
50
|
33
|
|
|
136
|
$tmp .= $dig[$n] unless ($n == 0 and $tmp =~ $zero) |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
175
|
|
|
|
|
|
|
or ($_ == 1 and $n == 1 and not $tmp); |
176
|
20
|
50
|
|
|
|
47
|
$tmp .= $ord[$_] if $n; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
12
|
50
|
|
|
|
41
|
$tmp =~ s/$zero// unless $tmp eq $dig[0]; |
180
|
12
|
100
|
|
|
|
25
|
$tmp .= $mag[$mag] if $tmp; |
181
|
12
|
50
|
66
|
|
|
40
|
$tmp = $dig[0].$tmp if $num < 1000 and $mag != $#chunks |
|
|
|
33
|
|
|
|
|
182
|
|
|
|
|
|
|
and $out !~ $zero; |
183
|
12
|
|
|
|
|
17
|
$out .= $tmp; |
184
|
12
|
|
|
|
|
31
|
$mag--; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
8
|
50
|
|
|
|
643
|
$out =~ s/$zero// unless $out eq $dig[0]; |
188
|
|
|
|
|
|
|
|
189
|
8
|
50
|
|
|
|
17
|
if ($delta) { |
190
|
0
|
|
|
|
|
0
|
$delta =~ s/^0\.//; |
191
|
0
|
|
|
|
|
0
|
$out .= $dot; |
192
|
0
|
|
|
|
|
0
|
$out .= $dig[$_] for split(//, $delta); |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
8
|
|
66
|
|
|
61
|
return $out || $dig[0]; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# }}} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
1; |
201
|
|
|
|
|
|
|
__END__ |