• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

savoirfairelinux / num2words / 6098159229

06 Sep 2023 02:02PM UTC coverage: 97.424% (+4.8%) from 92.579%
6098159229

Pull #492

github

web-flow
Merge 3e39091d0 into f2fb5bc67
Pull Request #492: 2 Issues Potentially Fixed

2978 of 3140 branches covered (0.0%)

Branch coverage included in aggregate %.

3683 of 3696 new or added lines in 84 files covered. (99.65%)

3 existing lines in 1 file now uncovered.

8102 of 8233 relevant lines covered (98.41%)

4.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.57
/num2words/lang_ID.py
1
# -*- coding: utf-8 -*-
2
# Copyright (c) 2003, Taro Ogawa.  All Rights Reserved.
3
# Copyright (c) 2013, Savoir-faire Linux inc.  All Rights Reserved.
4

5
# This library is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU Lesser General Public
7
# License as published by the Free Software Foundation; either
8
# version 2.1 of the License, or (at your option) any later version.
9
# This library is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
# Lesser General Public License for more details.
13
# You should have received a copy of the GNU Lesser General Public
14
# License along with this library; if not, write to the Free Software
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
# MA 02110-1301 USA
17

18
from __future__ import print_function, unicode_literals
5✔
19

20

21
class Num2Word_ID():
5✔
22
    BASE = {0: [],
5✔
23
            1: ["satu"],
24
            2: ["dua"],
25
            3: ["tiga"],
26
            4: ["empat"],
27
            5: ["lima"],
28
            6: ["enam"],
29
            7: ["tujuh"],
30
            8: ["delapan"],
31
            9: ["sembilan"]}
32

33
    TENS_TO = {3: "ribu",
5✔
34
               6: "juta",
35
               9: "miliar",
36
               12: "triliun",
37
               15: "kuadriliun",
38
               18: "kuantiliun",
39
               21: "sekstiliun",
40
               24: "septiliun",
41
               27: "oktiliun",
42
               30: "noniliun",
43
               33: "desiliun"}
44

45
    errmsg_floatord = "Cannot treat float number as ordinal"
5✔
46
    errmsg_negord = "Cannot treat negative number as ordinal"
5✔
47
    errmsg_toobig = "Number is too large to convert to words (abs(%s) > %s)."
5✔
48
    MAXVAL = 10 ** 36
5✔
49

50
    def split_by_koma(self, number):
5✔
51
        return str(number).split('.')
5✔
52

53
    def split_by_3(self, number):
5✔
54
        """
55
        starting here, it groups the number by three from the tail
56
        '1234567' -> (('1',),('234',),('567',))
57
        :param number:str
58
        :rtype:tuple
59
        """
60
        blocks = ()
5✔
61
        length = len(number)
5✔
62

63
        if length < 3:
5✔
64
            blocks += ((number,),)
5✔
65
        else:
66
            len_of_first_block = length % 3
5✔
67

68
            if len_of_first_block > 0:
5✔
69
                first_block = number[0:len_of_first_block],
5✔
70
                blocks += first_block,
5✔
71

72
            for i in range(len_of_first_block, length, 3):
5✔
73
                next_block = (number[i:i + 3],),
5✔
74
                blocks += next_block
5✔
75

76
        return blocks
5✔
77

78
    def spell(self, blocks):
5✔
79
        """
80
        it adds the list of spelling to the blocks
81
        (
82
        ('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat'])
83
        )
84
        :param blocks: tuple
85
        :rtype: tuple
86
        """
87
        word_blocks = ()
5✔
88
        first_block = blocks[0]
5✔
89
        if len(first_block[0]) == 1:
5✔
90
            if first_block[0] == '0':
5✔
91
                spelling = ['nol']
5✔
92
            else:
93
                spelling = self.BASE[int(first_block[0])]
5✔
94
        elif len(first_block[0]) == 2:
5✔
95
            spelling = self.puluh(first_block[0])
5✔
96
        else:
97
            spelling = (
5✔
98
                self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
99
                )
100

101
        word_blocks += (first_block[0], spelling),
5✔
102

103
        for block in blocks[1:]:
5✔
104
            spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
5✔
105
            block += spelling,
5✔
106
            word_blocks += block,
5✔
107

108
        return word_blocks
5✔
109

110
    def ratus(self, number):
5✔
111
        # it is used to spell
112
        if number == '1':
5✔
113
            return ['seratus']
5✔
114
        elif number == '0':
5✔
115
            return []
5✔
116
        else:
117
            return self.BASE[int(number)] + ['ratus']
5✔
118

119
    def puluh(self, number):
5✔
120
        # it is used to spell
121
        if number[0] == '1':
5✔
122
            if number[1] == '0':
5✔
123
                return ['sepuluh']
5✔
124
            elif number[1] == '1':
5✔
125
                return ['sebelas']
5✔
126
            else:
127
                return self.BASE[int(number[1])] + ['belas']
5✔
128
        elif number[0] == '0':
5✔
129
            return self.BASE[int(number[1])]
5✔
130
        else:
131
            return (
5✔
132
                self.BASE[int(number[0])] + ['puluh']
133
                + self.BASE[int(number[1])]
134
            )
135

136
    def spell_float(self, float_part):
5✔
137
        # spell the float number
138
        word_list = []
5✔
139
        for n in float_part:
5✔
140
            if n == '0':
5✔
141
                word_list += ['nol']
5✔
142
                continue
5✔
143
            word_list += self.BASE[int(n)]
5✔
144
        return ' '.join(['', 'koma'] + word_list)
5✔
145

146
    def join(self, word_blocks, float_part):
5✔
147
        """
148
        join the words by first join lists in the tuple
149
        :param word_blocks: tuple
150
        :rtype: str
151
        """
152
        word_list = []
5✔
153
        length = len(word_blocks) - 1
5✔
154
        first_block = word_blocks[0],
5✔
155
        start = 0
5✔
156

157
        if length == 1 and first_block[0][0] == '1':
5✔
158
            word_list += ['seribu']
5✔
159
            start = 1
5✔
160

161
        for i in range(start, length + 1, 1):
5!
162
            word_list += word_blocks[i][1]
5✔
163
            if not word_blocks[i][1]:
5✔
164
                continue
5✔
165
            if i == length:
5✔
166
                break
5✔
167
            word_list += [self.TENS_TO[(length - i) * 3]]
5✔
168

169
        return ' '.join(word_list) + float_part
5✔
170

171
    def to_cardinal(self, number):
5✔
172
        if number >= self.MAXVAL:
5!
NEW
173
            raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL))
×
174
        minus = ''
5✔
175
        if number < 0:
5✔
176
            minus = 'min '
5✔
177
        float_word = ''
5✔
178
        n = self.split_by_koma(abs(number))
5✔
179
        if len(n) == 2:
5✔
180
            float_word = self.spell_float(n[1])
5✔
181
        return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
5✔
182

183
    def to_ordinal(self, number):
5✔
184
        self.verify_ordinal(number)
5✔
185
        out_word = self.to_cardinal(number)
5✔
186
        if out_word == "satu":
5✔
187
            return "pertama"
5✔
188
        return "ke" + out_word
5✔
189

190
    def to_ordinal_num(self, number):
5✔
191
        self.verify_ordinal(number)
×
192
        return "ke-" + str(number)
×
193

194
    def to_currency(self, value):
5✔
195
        return self.to_cardinal(value) + " rupiah"
×
196

197
    def to_year(self, value):
5✔
198
        return self.to_cardinal(value)
×
199

200
    def verify_ordinal(self, value):
5✔
201
        if not value == int(value):
5✔
202
            raise TypeError(self.errmsg_floatord % value)
5✔
203
        if not abs(value) == value:
5✔
204
            raise TypeError(self.errmsg_negord % value)
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc