使人类可读的整数表示

时间:2020-03-05 18:39:42  来源:igfitidea点击:

对于那些喜欢这种东西的人来说,这是一个编码问题。让我们看看函数的实现(当然,使用我们选择的语言),该函数返回人类可读的指定Integer的String表示形式。例如:

humanReadable(1)返回"一个"。
humanReadable(53)返回"五十三个"。
humanReadable(723603)返回"七十二万三千六百三十三"。
humanReadable(1456376562)返回"十亿,四亿五千六百万,三百七十六万六千,五百六十二"。

奖励积分,可提供特别巧妙/优雅的解决方案!

这看似毫无意义,但是在现实世界中有很多此类算法的应用(尽管支持多达十亿个算法可能是过分的了:-)

解决方案

回答

已经有一个关于这个的问题:
将整数转换为书面数字

答案是针对C#的,但我认为我们可以弄清楚。

回答

支持多达9亿9千9百万个,但没有负数:

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";
  }
}

回答

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

回答

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();
        }
    }
}

回答

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

回答

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

自从几乎永远以来,它就一直是bsdgames的一部分...

> man number