Создание удобочитаемых представлений целого числа

Вот проблема кодирования для тех, кто любит такие вещи. Давайте посмотрим, как вы реализуете (конечно, на выбранном вами языке) функцию, которая возвращает читаемое человеком представление String указанного целого числа. Например:

  • humanReadable (1) возвращает «один».
  • humanReadable (53) возвращает «пятьдесят три».
  • humanReadable (723603) возвращает «семьсот двадцать три тысячи шестьсот три».
  • humanReadable (1456376562) возвращает «один миллиард четыреста пятьдесят шесть миллионов триста семьдесят шесть тысяч пятьсот шестьдесят два».

Бонусные баллы за особенно умные / элегантные решения!

Это может показаться бессмысленным упражнением, но существует множество реальных приложений для такого рода алгоритма (хотя поддержка чисел до миллиарда может быть излишней :-)

14.08.2008 17:25:29
Звучит как домашнее задание или вопрос на собеседовании, вы должны сделать это самостоятельно.
leppie 16.10.2008 06:48:54
Для тех , кто погуглить о том , как сделать , например , 12,254из 12254вас может сделать12254.to_s.reverse.split('').each_slice(3).to_a.map{|x|x=x.join().reverse}.reverse.join(',')
xxjjnn 21.11.2014 15:27:54
6 ОТВЕТОВ
РЕШЕНИЕ

Уже был вопрос по этому поводу: конвертировать целые числа в записанные числа

Ответ для C #, но я думаю, что вы можете понять это.

8
23.05.2017 12:33:26

Поддерживает до 999 миллионов, но без отрицательных чисел:

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";
  }
}
1
14.08.2008 17:55:35
Вы забыли указать язык.
Lightness Races in Orbit 21.04.2011 00:36:34
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
3
14.08.2008 18:11:33
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();
        }
    }
}
1
14.08.2008 18:17:02

Существует одна огромная проблема в реализации этой функции. Это будущая локализация. Эта функция, написанная носителем английского языка, скорее всего, не будет работать правильно для любого другого языка, кроме английского. Почти невозможно написать общую легкую локализуемую функцию для любого диалекта человеческого языка в мире, если вам действительно не нужно, чтобы она была общей. На самом деле в реальном мире вам не нужно работать с огромными целыми числами, поэтому вы можете просто хранить все числа в большом (или даже не очень) массиве строк.

0
14.10.2008 13:18:47
В CLDR есть информация о том, как выписанные числа работают на каждом языке, но я не смог найти пример кода для работы с ним, чтобы на самом деле генерировать числа.
Random832 17.05.2011 19:18:18

согласился, что есть ряд реальных приложений. в качестве такового уже существует ряд реализаций реального мира.

это было частью bsdgames, так как почти навсегда ...

> man number
0
18.10.2008 01:30:01