将数字转换为英文字符串 [英] Convert numbers to English strings
问题描述
http://www.easysurf.cc/cnvert18.htm 和 http://www.calculatorsoup.com/calculators/conversions/numberstowords.php 尝试将数字字符串转换为英语字符串,但是它们提供了自然的声音输出.
Websites like http://www.easysurf.cc/cnvert18.htm and http://www.calculatorsoup.com/calculators/conversions/numberstowords.php tries to convert a numerical string into an english strings, but they are giving natural sounding output.
例如,在 http://www.easysurf.cc/cnvert18.htm 上:
[in]: 100456
[out]: one hundred thousand four hundred fifty-six
该网站要好一些, http://www.calculator .org/calculate-online/mathematics/text-number.aspx :
[in]: 100456
[out]: one hundred thousand, four hundred and fifty-six
[in]: 10123124001
[out]: ten billion, one hundred and twenty-three million, one hundred and twenty-four thousand, one
但它在某些时候中断了:
but it breaks at some point:
[in]: 10000000001
[out]: ten billion, , , one
我已经编写了自己的版本,但其中涉及许多规则,其上限为10亿个. http://pastebin .com/WwFCjYtt :
I've wrote my own version but it involves lots of rules and it caps at one billion, from http://pastebin.com/WwFCjYtt:
import codecs
def num2word (num):
ones = {1:"one",2:"two",3:"three",4:"four",
5:"five",6:"six",7:"seven",8:"eight",
9:"nine",0:"zero",10:"ten"}
teens = {11:"eleven",12:"twelve",13:"thirteen",
14:"fourteen",15:"fifteen"}
tens = {2:"twenty",3:"thirty",4:"forty",
5:"fifty",6:"sixty",7:"seventy",
8:"eighty",9:"ninety"}
lens = {3:"hundred",4:"thousand",6:"hundred",7:"million",
8:"million", 9:"million",10:"billion"#,13:"trillion",11:"googol",
}
if num > 999999999:
return "Number more than 1 billion"
# Ones
if num < 11:
return ones[num]
# Teens
if num < 20:
word = ones[num%10] + "teen" if num > 15 else teens[num]
return word
# Tens
if num > 19 and num < 100:
word = tens[int(str(num)[0])]
if str(num)[1] == "0":
return word
else:
word = word + " " + ones[num%10]
return word
# First digit for thousands,hundred-thousands.
if len(str(num)) in lens and len(str(num)) != 3:
word = ones[int(str(num)[0])] + " " + lens[len(str(num))]
else:
word = ""
# Hundred to Million
if num < 1000000:
# First and Second digit for ten thousands.
if len(str(num)) == 5:
word = num2word(int(str(num)[0:2])) + " thousand"
# How many hundred-thousand(s).
if len(str(num)) == 6:
word = word + " " + num2word(int(str(num)[1:3])) + \
" " + lens[len(str(num))-2]
# How many hundred(s)?
thousand_pt = len(str(num)) - 3
word = word + " " + ones[int(str(num)[thousand_pt])] + \
" " + lens[len(str(num))-thousand_pt]
# Last 2 digits.
last2 = num2word(int(str(num)[-2:]))
if last2 != "zero":
word = word + " and " + last2
word = word.replace(" zero hundred","")
return word.strip()
left, right = '',''
# Less than 1 million.
if num < 100000000:
left = num2word(int(str(num)[:-6])) + " " + lens[len(str(num))]
right = num2word(int(str(num)[-6:]))
# From 1 million to 1 billion.
if num > 100000000 and num < 1000000000:
left = num2word(int(str(num)[:3])) + " " + lens[len(str(num))]
right = num2word(int(str(num)[-6:]))
if int(str(num)[-6:]) < 100:
word = left + " and " + right
else:
word = left + " " + right
word = word.replace(" zero hundred","").replace(" zero thousand"," thousand")
return word
print num2word(int(raw_input("Give me a number:\n")))
如何使我编写的脚本接受> billion
?
How can I make the script i've wrote accept > billion
?
还有其他方法可以获得相同的输出吗?
我的代码可以用不太冗长的方式编写吗?
推荐答案
针对此问题的更通用方法是使用重复除法(即divmod
),并且仅对必要的特殊情况/边缘情况进行硬编码.
A more general approach to this problem uses repeated division (i.e. divmod
) and only hardcodes the special/edge cases necessary.
例如divmod(1034393, 1000000) -> (1, 34393)
,因此您已经有效地找到了数百万,并剩下了余数以进行进一步的计算.
For example, divmod(1034393, 1000000) -> (1, 34393)
, so you've effectively found the number of millions and are left with a remainder for further calculations.
可能是更具说明性的示例:divmod(1034393, 1000) -> (1034, 393)
,使您可以一次从右侧取下3个十进制数字组成的组.
Possibly more illustrative example: divmod(1034393, 1000) -> (1034, 393)
which allows you to take off groups of 3 decimal digits at a time from the right.
在英语中,我们倾向于将数字分为三部分,并且适用类似的规则.这应该被参数化,而不是硬编码.例如,"303"可以是三百三十万,十三万三千或三百三十.除了后缀之外,逻辑应该相同,具体取决于您所处的位置.由于递归,看起来有点像在那儿.
In English we tend to group digits in threes, and similar rules apply. This should be parameterized and not hard coded. For example, "303" could be three hundred and three million, three hundred and three thousand, or three hundred and three. The logic should be the same except for the suffix, depending on what place you're in. looks like this is sort of there due to recursion.
这是我的意思是这种方法的部分示例,它使用生成器并对整数进行操作,而不是在各处都执行许多int(str(i)[..])
.
Here is a partial example of the kind of approach I mean, using a generator and operating on integers rather than doing lots of int(str(i)[..])
everywhere.
say_base = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven',
'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen',
'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
say_tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy',
'eighty', 'ninety']
def hundreds_i(num):
hundreds, rest = divmod(num, 100)
if hundreds:
yield say_base[hundreds]
yield ' hundred'
if 0 < rest < len(say_base):
yield ' and '
yield say_base[rest]
elif rest != 0:
tens, ones = divmod(rest, 10)
yield ' and '
yield say_tens[tens]
if ones > 0:
yield '-'
yield say_base[ones]
assert "".join(hundreds_i(245)) == "two hundred and forty-five"
assert "".join(hundreds_i(999)) == 'nine hundred and ninety-nine'
assert "".join(hundreds_i(200)) == 'two hundred'
这篇关于将数字转换为英文字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!