【问题标题】:Making human readable representations of an Integer制作人类可读的整数表示
【发布时间】:2010-09-05 21:34:11
【问题描述】:

对于喜欢这种东西的人来说,这是一个编码问题。让我们看看你对一个函数的实现(当然是用你选择的语言),它返回一个指定整数的人类可读的字符串表示。例如:

  • humanReadable(1) 返回“一”。
  • humanReadable(53) 返回“五十三”。
  • humanReadable(723603) 返回“七十二万三千六百零三”。
  • humanReadable(1456376562) 返回“十亿、四亿五千六百万、三十七万六千、五百六十二”。

特别聪明/优雅的解决方案的奖励积分!

这似乎是一个毫无意义的练习,但这种算法在现实世界中有很多应用程序(尽管支持高达 10 亿的数字可能有点矫枉过正 :-)

【问题讨论】:

  • 听起来像是作业或面试问题,你应该自己做。
  • 对于任何在谷歌上搜索如何做的人,例如12,254 来自12254可以12254.to_s.reverse.split('').each_slice(3).to_a.map{|x|x=x.join().reverse}.reverse.join(',')

标签: algorithm numbers


【解决方案1】:

已经有一个关于这个的问题: Convert integers to written numbers

答案是 C#,但我想你可以弄清楚。

【讨论】:

    【解决方案2】:

    最多支持9.99亿,但没有负数:

    String humanReadable(int inputNumber) {
      if (inputNumber == -1) {
        return "";
      }
      int remainder;
      int quotient;
      quotient = inputNumber / 1000000;
      remainder = inputNumber % 1000000;
      if (quotient > 0) {
        return humanReadable(quotient) + " million, " + humanReadable(remainder);
      }
      quotient = inputNumber / 1000;
      remainder = inputNumber % 1000;
      if (quotient > 0) {
        return humanReadable(quotient) + " thousand, " + humanReadable(remainder);
      }
      quotient = inputNumber / 100;
      remainder = inputNumber % 100;
      if (quotient > 0) {
        return humanReadable(quotient) + " hundred, " + humanReadable(remainder);
      }
      quotient = inputNumber / 10;
      remainder = inputNumber % 10;
      if (remainder == 0) {
        //hackish way to flag the algorithm to not output something like "twenty zero"
        remainder = -1;
      }
      if (quotient == 1) {
        switch(inputNumber) {
        case 10:
          return "ten";
        case 11:
          return "eleven";
        case 12:
          return "twelve";
        case 13:
          return "thirteen";
        case 14:
          return "fourteen";
        case 15:
          return "fifteen";
        case 16:
          return "sixteen";
        case 17:
          return "seventeen";
        case 18:
          return "eighteen";
        case 19:
          return "nineteen";
        }
      }
      switch(quotient) {
      case 2:
        return "twenty " + humanReadable(remainder);
      case 3:
        return "thirty " + humanReadable(remainder);
      case 4:
        return "forty " + humanReadable(remainder);
      case 5:
        return "fifty " + humanReadable(remainder);
      case 6:
        return "sixty " + humanReadable(remainder);
      case 7:
        return "seventy " + humanReadable(remainder);
      case 8:
        return "eighty " + humanReadable(remainder);
      case 9:
        return "ninety " + humanReadable(remainder);
      }
      switch(inputNumber) {
      case 0:
        return "zero";
      case 1:
        return "one";
      case 2:
        return "two";
      case 3:
        return "three";
      case 4:
        return "four";
      case 5:
        return "five";
      case 6:
        return "six";
      case 7:
        return "seven";
      case 8:
        return "eight";
      case 9:
        return "nine";
      }
    }
    

    【讨论】:

    • 你忘了说明语言。
    【解决方案3】:
    import math
    
    def encodeOnesDigit(num):
       return ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'][num]
    
    def encodeTensDigit(num):
       return ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety'][num-2]
    
    def encodeTeens(num):
       if num < 10:
          return encodeOnesDigit(num)
       else:
          return ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'][num-10]
    
    def encodeTriplet(num):
       if num == 0: return ''
       str = ''
       if num >= 100:
          str = encodeOnesDigit(num / 100) + ' hundred'
       tens = num % 100
       if tens >= 20:
          if str != '': str += ' '
          str += encodeTensDigit(tens / 10)
          if tens % 10 > 0:
             str += '-' + encodeOnesDigit(tens % 10)
       elif tens != 0:
          if str != '': str += ' '
          str += encodeTeens(tens)
       return str
    
    def zipNumbers(numList):
       if len(numList) == 1:
          return numList[0]
       strList = ['', ' thousand', ' million', ' billion'] # Add more as needed
       strList = strList[:len(numList)]
       strList.reverse()
       joinedList = zip(numList, strList)
       joinedList = [item for item in joinedList if item[0] != '']
       return ', '.join(''.join(item) for item in joinedList)
    
    def humanReadable(num):
       if num == 0: return 'zero'
       negative = False
       if num < 0:
          num *= -1
          negative = True
       numString = str(num)
       tripletCount = int(math.ceil(len(numString) / 3.0))
       numString = numString.zfill(tripletCount * 3)
       tripletList = [int(numString[i*3:i*3+3]) for i in range(tripletCount)]
       readableList = [encodeTriplet(num) for num in tripletList]
       readableStr = zipNumbers(readableList)
       return 'negative ' + readableStr if negative else readableStr
    

    【讨论】:

      【解决方案4】:
      using System;
      
      namespace HumanReadable
      {
          public static class HumanReadableExt
          {
              private static readonly string[] _digits = {
                                                             "", "one", "two", "three", "four", "five",
                                                             "six", "seven", "eight", "nine", "eleven", "twelve",
                                                             "thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
                                                             "eighteen", "nineteen"
                                                         };
      
              private static readonly string[] _teens = {
                                                            "", "", "twenty", "thirty", "forty", "fifty",
                                                            "sixty", "seventy", "eighty", "ninety"
                                                        };
      
              private static readonly string[] _illions = {
                                                              "", "thousand", "million", "billion", "trillion"
                                                          };
      
              private static string Seg(int number)
              {
                  var work = string.Empty;
      
                  if (number >= 100) 
                      work += _digits[number / 100] + " hundred ";
      
                  if ((number % 100) < 20)
                      work += _digits[number % 100];
                  else
                      work += _teens[(number % 100) / 10] + "-" + _digits[number % 10];
      
                  return work;
              }
      
              public static string HumanReadable(this int number)
              {
                  if (number == 0)
                      return "zero";
                  var work = string.Empty;
      
                  var parts = new string[_illions.Length];
      
                  for (var ind = 0; ind < parts.Length; ind++)
                      parts[ind] = Seg((int) (number % Math.Pow(1000, ind + 1) / Math.Pow(1000, ind)));
      
                  for (var ind = 0; ind < parts.Length; ind++)
                      if (!string.IsNullOrEmpty(parts[ind]))
                          work = parts[ind] + " " + _illions[ind] + ", " + work;
      
                  work = work.TrimEnd(',', ' ');
      
                  var lastSpace = work.LastIndexOf(' ');
                  if (lastSpace >= 0)
                      work = work.Substring(0, lastSpace) + " and" + work.Substring(lastSpace);
      
                  return work;
              }
          }
      
          class Program
          {
      
              static void Main(string[] args)
              {
                  Console.WriteLine(1.HumanReadable());
                  Console.WriteLine(53.HumanReadable());
                  Console.WriteLine(723603.HumanReadable());
                  Console.WriteLine(1456376562.HumanReadable());
                  Console.ReadLine();
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        这个函数的实现存在一个大问题。这是它未来的本地化。该功能由英语为母语的人编写,很可能不适用于英语以外的任何其他语言。几乎不可能为世界上的任何人类语言方言编写通用的易于本地化的函数,除非你真的需要保持它的通用性。实际上,在现实世界中,您不需要使用巨大的整数进行操作,因此您可以将所有数字保存在一个大(甚至不是那么大)的字符串数组中。

        【讨论】:

        • CLDR 中有关于在每种语言中写出的数字如何工作的信息,但我找不到任何示例代码来使用它来实际生成数字。
        【解决方案6】:

        同意有许多现实世界的应用程序。 因此,已经有许多现实世界的实现。

        它几乎永远是 bsdgames 的一部分......

        > man number
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-15
          • 2013-09-01
          相关资源
          最近更新 更多