将数字转换为英文字符串 [英] Convert numbers to English strings

查看:134
本文介绍了将数字转换为英文字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆