Сведения о вопросе

Oleksandr

08:24, 9th August, 2020

Теги

algorithm   numbers    

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

Просмотров: 480   Ответов: 6

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

  • humanReadable (1) возвращает "one".
  • humanReadable (53) возвращает "fifty-three".
  • humanReadable (723603) возвращает "seven hundred and twenty-three thousand, six hundred and three".
  • humanReadable(1456376562) возвращает "один миллиард четыреста пятьдесят шесть миллионов триста семьдесят шесть тысяч пятьсот шестьдесят два".

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

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



  Сведения об ответе

lesha

18:29, 27th August, 2020

Об этом уже был вопрос: Преобразование целых чисел в записанные числа

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


  Сведения об ответе

PAGE

15:13, 14th August, 2020

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


  Сведения об ответе

SKY

10:38, 21st August, 2020

Поддерживает до 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";
  }
}


  Сведения об ответе

9090

15:40, 15th August, 2020

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


  Сведения об ответе

$DOLLAR

07:05, 13th August, 2020

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

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

> man number


  Сведения об ответе

+-*/

15:22, 2nd August, 2020

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться