line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Lingua::ZH::Numbers; |
2
|
|
|
|
|
|
|
$Lingua::ZH::Numbers::VERSION = '0.04'; |
3
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
1391
|
use 5.001; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
171
|
|
5
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
6
|
1
|
|
|
1
|
|
5
|
use Exporter; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
47
|
|
7
|
1
|
|
|
1
|
|
5
|
use base 'Exporter'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
121
|
|
8
|
1
|
|
|
1
|
|
6
|
use vars qw($Charset %MAP $VERSION @EXPORT); |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
747
|
|
9
|
|
|
|
|
|
|
@EXPORT = 'number_to_zh'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 NAME |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
Lingua::ZH::Numbers - Converts numeric values into their Chinese string equivalents |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 VERSION |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
This document describes version 0.04 of Lingua::ZH::Numbers, released |
18
|
|
|
|
|
|
|
September 8, 2004. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=head1 SYNOPSIS |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# OO Style |
23
|
|
|
|
|
|
|
use Lingua::ZH::Numbers 'pinyin'; |
24
|
|
|
|
|
|
|
my $shuzi = Lingua::ZH::Numbers->new( 123 ); |
25
|
|
|
|
|
|
|
print $shuzi->get_string; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $lingyige_shuzi = Lingua::ZH::Numbers->new; |
28
|
|
|
|
|
|
|
$lingyige_shuzi->parse( 7340 ); |
29
|
|
|
|
|
|
|
$chinese_string = $lingyige_shuzi->get_string; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Function style |
32
|
|
|
|
|
|
|
print number_to_zh( 345 ); # automatically exported |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Change output format |
35
|
|
|
|
|
|
|
Lingua::ZH::Numbers->charset('big5'); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head1 DESCRIPTION |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
This module tries to convert a number into Chinese cardinal number. |
40
|
|
|
|
|
|
|
It supports decimals number, and five representation systems |
41
|
|
|
|
|
|
|
(I): C, C, C, C and |
42
|
|
|
|
|
|
|
C. The first two are returned as unicode strings; hence |
43
|
|
|
|
|
|
|
they are only available for Perl 5.6 and later versions. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
The interface conforms to the one defined in B, |
46
|
|
|
|
|
|
|
but you can also use this module in a functionnal manner by invoking |
47
|
|
|
|
|
|
|
the C function. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Global Constants {{{ |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
$Charset = 'pinyin'; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
%MAP = ( |
56
|
|
|
|
|
|
|
($] >= 5.006) ? eval q( |
57
|
|
|
|
|
|
|
'traditional' => { |
58
|
|
|
|
|
|
|
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}") ], |
59
|
|
|
|
|
|
|
ord => [ '', split(' ', "\x{5341} \x{767e} \x{5343}") ], |
60
|
|
|
|
|
|
|
dig => [ split(' ', "\x{96f6} \x{4e00} \x{4e8c} \x{4e09} \x{56db} \x{4e94} \x{516d} \x{4e03} \x{516b} \x{4e5d} \x{5341}") ], |
61
|
|
|
|
|
|
|
dot => "\x{9ede}", |
62
|
|
|
|
|
|
|
neg => "\x{8ca0}", |
63
|
|
|
|
|
|
|
}, |
64
|
|
|
|
|
|
|
'simplified' => { |
65
|
|
|
|
|
|
|
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}") ], |
66
|
|
|
|
|
|
|
ord => [ '', split(' ', "\x{5341} \x{767e} \x{5343}") ], |
67
|
|
|
|
|
|
|
dig => [ split(' ', "\x{96f6} \x{4e00} \x{4e8c} \x{4e09} \x{56db} \x{4e94} \x{516d} \x{4e03} \x{516b} \x{4e5d} \x{5341}") ], |
68
|
|
|
|
|
|
|
dot => "\x{70b9}", |
69
|
|
|
|
|
|
|
neg => "\x{8d1f}", |
70
|
|
|
|
|
|
|
}, |
71
|
|
|
|
|
|
|
) : (), |
72
|
|
|
|
|
|
|
'big5' => { |
73
|
|
|
|
|
|
|
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") ], |
74
|
|
|
|
|
|
|
ord => [ '', split(' ', "\xA4Q \xA6\xCA \xA4d") ], |
75
|
|
|
|
|
|
|
dig => [ split(' ', "\xB9s \xA4\@ \xA4G \xA4T \xA5| \xA4\xAD \xA4\xBB \xA4C \xA4K \xA4E \xA4Q") ], |
76
|
|
|
|
|
|
|
dot => "\xC2I", |
77
|
|
|
|
|
|
|
neg => "\xADt", |
78
|
|
|
|
|
|
|
}, |
79
|
|
|
|
|
|
|
'gb' => { |
80
|
|
|
|
|
|
|
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") ], |
81
|
|
|
|
|
|
|
ord => [ '', split(' ', "\xCA\xAE \xB0\xD9 \xC7\xA7") ], |
82
|
|
|
|
|
|
|
dig => [ split(' ', "\xC1\xE3 \xD2\xBB \xB6\xFE \xC8\xFD \xCB\xC4 \xCE\xE5 \xC1\xF9 \xC6\xDF \xB0\xCB \xBE\xC5 \xCA\xAE") ], |
83
|
|
|
|
|
|
|
dot => "\xB5\xE3", |
84
|
|
|
|
|
|
|
neg => "\xB8\xBA", |
85
|
|
|
|
|
|
|
}, |
86
|
|
|
|
|
|
|
'pinyin' => { |
87
|
|
|
|
|
|
|
mag => [ '', map "$_ ", qw( |
88
|
|
|
|
|
|
|
Wan Yi Zhao Jing Gai Zi Rang Gou Jian Zheng Zai Ji |
89
|
|
|
|
|
|
|
HengHeSha AZengZhi NaYouTa BuKeSiYi WuLiangDaShu |
90
|
|
|
|
|
|
|
) ], |
91
|
|
|
|
|
|
|
ord => [ '', map "$_ ", qw(Shi Bai Qian) ], |
92
|
|
|
|
|
|
|
dig => [ qw(Ling Yi Er San Si Wu Liu Qi Ba Jiu Shi) ], |
93
|
|
|
|
|
|
|
dot => ' Dian ', |
94
|
|
|
|
|
|
|
neg => 'Fu ', |
95
|
|
|
|
|
|
|
}, |
96
|
|
|
|
|
|
|
); |
97
|
|
|
|
|
|
|
# }}} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub import { |
100
|
0
|
|
|
0
|
|
0
|
my ($class, $charset) = @_; |
101
|
0
|
|
|
|
|
0
|
$class->charset($charset); |
102
|
0
|
|
|
|
|
0
|
$class->export_to_level(1, $class); |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub charset { |
106
|
2
|
|
|
2
|
0
|
20
|
my ($class, $charset) = @_; |
107
|
|
|
|
|
|
|
|
108
|
1
|
|
|
1
|
|
7
|
no strict 'refs'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
1526
|
|
109
|
2
|
50
|
|
|
|
8
|
return ${"$class\::Charset"} unless defined $charset; |
|
0
|
|
|
|
|
0
|
|
110
|
|
|
|
|
|
|
|
111
|
2
|
50
|
33
|
|
|
27
|
$charset = 'gb' if $charset =~ /^gb/i or $charset =~ /^euc-cn$/i; |
112
|
2
|
50
|
|
|
|
13
|
$charset = 'big5' if $charset =~ /big5/i; |
113
|
2
|
50
|
|
|
|
3
|
${"$class\::Charset"} = lc($charset) if exists ${"$class\::MAP"}{lc($charset)}; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
18
|
|
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub map { |
117
|
1
|
|
|
1
|
0
|
7
|
return \%MAP; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub new { |
121
|
0
|
|
|
0
|
0
|
0
|
my ($class, $num) = @_; |
122
|
0
|
|
|
|
|
0
|
bless (\$num, $class); |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub parse { |
126
|
0
|
|
|
0
|
0
|
0
|
my ($self, $num) = @_; |
127
|
0
|
|
|
|
|
0
|
${$self} = $num; |
|
0
|
|
|
|
|
0
|
|
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub get_string { |
131
|
0
|
|
|
0
|
0
|
0
|
my ($self) = @_; |
132
|
0
|
|
|
|
|
0
|
return number_to_zh($$self); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub number_to_zh { |
136
|
3
|
|
|
3
|
0
|
24
|
__PACKAGE__->_convert($MAP{$Charset}, @_); |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
sub _convert { |
140
|
4
|
|
|
4
|
|
9
|
my ($class, $map, $input) = @_; |
141
|
4
|
|
|
|
|
10
|
$input =~ s/[^\d\.\-]//; |
142
|
|
|
|
|
|
|
|
143
|
4
|
|
|
|
|
6
|
my @dig = @{$map->{dig}}; |
|
4
|
|
|
|
|
17
|
|
144
|
4
|
|
|
|
|
5
|
my @ord = @{$map->{ord}}; |
|
4
|
|
|
|
|
12
|
|
145
|
4
|
|
|
|
|
6
|
my @mag = @{$map->{mag}}; |
|
4
|
|
|
|
|
20
|
|
146
|
4
|
|
|
|
|
5
|
my $dot = $map->{dot}; |
147
|
4
|
|
|
|
|
5
|
my $neg = $map->{neg}; |
148
|
|
|
|
|
|
|
|
149
|
4
|
|
|
|
|
7
|
my $out = ''; |
150
|
4
|
50
|
|
|
|
12
|
my $delta = $1 if $input =~ s/\.(.*)//; |
151
|
4
|
50
|
|
|
|
10
|
$out = $neg if $input =~ s/^\-//; |
152
|
4
|
|
|
|
|
7
|
$input =~ s/^0+//; |
153
|
4
|
|
100
|
|
|
16
|
$input ||= '0'; |
154
|
|
|
|
|
|
|
|
155
|
4
|
|
|
|
|
6
|
my @chunks; |
156
|
4
|
|
|
|
|
43
|
unshift @chunks, $1 while ($input =~ s/(\d{1,4})$//g); |
157
|
4
|
|
|
|
|
7
|
my $mag = $#chunks; |
158
|
4
|
50
|
|
|
|
372
|
my $zero = ($] >= 5.005) ? eval 'qr/$dig[0]$/' : quotemeta($dig[0]) . '$'; |
159
|
|
|
|
|
|
|
|
160
|
4
|
|
|
|
|
16
|
foreach my $num (@chunks) { |
161
|
7
|
|
|
|
|
11
|
my $tmp = ''; |
162
|
|
|
|
|
|
|
|
163
|
7
|
|
|
|
|
15
|
for (reverse 0..3) { |
164
|
28
|
|
|
|
|
50
|
my $n = int($num / (10 ** $_)) % 10; |
165
|
28
|
100
|
100
|
|
|
172
|
next unless $tmp or $n; |
166
|
15
|
50
|
33
|
|
|
79
|
$tmp .= $dig[$n] unless ($n == 0 and $tmp =~ $zero) |
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
33
|
|
|
|
|
167
|
|
|
|
|
|
|
or ($_ == 1 and $n == 1 and !$tmp); |
168
|
15
|
50
|
|
|
|
41
|
$tmp .= $ord[$_] if $n; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
7
|
50
|
|
|
|
29
|
$tmp =~ s/$zero// unless $tmp eq $dig[0]; |
172
|
7
|
100
|
|
|
|
280
|
$tmp .= $mag[$mag] if $tmp; |
173
|
7
|
50
|
66
|
|
|
31
|
$tmp = $dig[0].$tmp if $num < 1000 and $mag != $#chunks |
|
|
|
33
|
|
|
|
|
174
|
|
|
|
|
|
|
and $out !~ $zero; |
175
|
7
|
|
|
|
|
86
|
$out .= $tmp; |
176
|
7
|
|
|
|
|
13
|
$mag--; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
4
|
50
|
|
|
|
20
|
$out =~ s/$zero// unless $out eq $dig[0]; |
180
|
|
|
|
|
|
|
|
181
|
4
|
50
|
|
|
|
33
|
if ($delta) { |
182
|
0
|
|
|
|
|
0
|
$delta =~ s/^0\.//; |
183
|
0
|
|
|
|
|
0
|
$out .= $dot; |
184
|
0
|
|
|
|
|
0
|
$out .= $dig[$_] for split(//, $delta); |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
4
|
|
66
|
|
|
277
|
return $out || $dig[0]; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
1; |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head1 SEE ALSO |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
L |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head1 ACKNOWLEDGMENTS |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Sean Burke for suggesting me to write this module. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head1 AUTHORS |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
Autrijus Tang Eautrijus@autrijus.orgE |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
=head1 COPYRIGHT |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
Copyright 2002, 2003, 2004 by Autrijus Tang Eautrijus@autrijus.orgE. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
209
|
|
|
|
|
|
|
under the same terms as Perl itself. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
See L |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=cut |