如何改进这个数字转文字脚本
import sys
words = {
1 : 'one',
2 : 'two',
3 : 'three',
4 : 'four',
5 : 'five',
6 : 'six',
7 : 'seven',
8 : 'eight',
9 : 'nine',
10 : 'ten',
11 : 'eleven',
12 : 'twelve',
13 : 'thirteen',
14 : 'fourteen',
15 : 'fifteen',
16 : 'sixteen',
17 : 'seventeen',
18 : 'eighteen',
19 : 'nineteen'
}
tens = [
'',
'twenty',
'thirty',
'forty',
'fifty',
'sixty',
'seventy',
'eighty',
'ninety',
]
placeholders = [
'',
'thousand',
'million',
'billion',
'trillion',
'quadrillion'
]
# segMag = segment magnitude (starting at 1)
def convertTrio(number):
return ' '.join([words[int(number[0])], 'hundred', convertDuo(number[1:3])]) # convertDuo(number[1:3])
def convertDuo(number):
#if teens or less
if int(number[0]) == 1:
return words[int(number)]
#twenty-five
else:
return tens[int(number[0]) - 1] + '-' + words[int(number[1])]
if __name__ == "__main__":
string = []
numeralSegments = []
numeral = sys.argv[1]
if int(numeral) < 100:
print convertDuo(numeral)
else:
# split number into lists, grouped in threes
for i in range (0, len(numeral), 3):
numeralSegments.append(numeral[i:i+3])
numeralSegments.reverse()
# for every segment, convert to trio word and append thousand, million, etc depending on magnitude
for i in range (len(numeralSegments)):
string.append(convertTrio(numeralSegments[i]) + ' ' + placeholders[i])
# reverse the list of strings before concatenating to commas
string.reverse()
print ', '.join(string)
警告: 我对Python完全是个新手。我知道可能有很多更高效的方法来完成这些事情。如果你能给我一些建议,我会非常感激。
编辑: 目前这段代码只适用于数字位数是三的倍数的情况。如果你能给我一个优雅的解决方案来修复这个问题,我也会很感激。谢谢。
6 个回答
2
与其去切分数字,不如用取模运算来分开个位数和十位数。这个函数可以把小于100的数字转换成你需要的格式。
def convert(n):
q, r = divmod(n, 10)
if q < 2:
return words[n]
result = tens[q-1] # offset because tens is missing first null value
if r:
result += '-' + words[r]
return result
接着可以用递归的方法来处理更大的数字,比如可以先用 divmod(n, 100) 来开始,然后继续处理下去。
2
你不能从左到右把数字分成“段”。使用 range(0,len(),3)
这样的写法是行不通的。你需要写一个算法来插入数字分隔符。这个过程是从右边开始,逐段取出数字。
剩下的部分(在左边,明白了吗?)会是1、2或3个数字。你有 convertTrio
和 convertDuo
,分别处理3个和2个数字。里面还有一个处理1个数字的函数(我看不到)。
如果这不是作业的话,下面是一个合适的数字聚合算法。
def segment( n ):
segList= []
while len(n) > 3:
segList.insert( 0, n[-3:] )
n= n[:-3]
segList.insert( 0, n )
return segList
编辑
为了让代码更符合Python的风格,可以把它整理成一个整洁、可重用的模块。if __name__ == "__main__"
里面的内容做了两件事,这两件事应该分开。
你的命令行解析(任何与 sys.argv
相关的内容)是一回事。而实际的“转换数字”的功能则是另一回事。你希望看起来更像这样。
if __name__ == "__main__":
import sys
for number in sys.argv[1:]:
print number2string( number )
这样,你的 number2string
函数就变成了这个模块中一个容易重用的部分。