Как пребразовать число в текст на JavaScript?

Рейтинг: 0Ответов: 2Опубликовано: 26.05.2023

Мне надо преобразовать строку в текст, например:

  • 123 в "сто двадцать три";
  • 351 в "триста пятьдесят один";
  • 11 в "одиннадцать";
  • -89 в "минус восемьдесят девять";
  • И так далее.

Скрипт должен преобразовывать число от -999 до 999.

Как это можно сделать?

Ответы

▲ 3Принят

const numberInWords = n => {
    if (Number.isNaN(n)) {
        return '?';
    }
    if (n === 0) {
        return 'ноль';
    }

    const result = [];
    if (n < 0) {
        result.push('минус');
        n = -n;
    }

    const u = n % 10;
    const t = Math.floor(n % 100 / 10);
    const h = Math.floor(n / 100);

    if (h > 0) {
        result.push([
            undefined, 'сто'     , 'двести' , 'триста'   , 'четыреста',
            'пятьсот', 'шестьсот', 'семьсот', 'восемьсот', 'девятьсот'
        ][h]);
    }

    if (t === 1) {
        result.push([
            'десять'      , 'одиннадцать' ,
            'двенадцать'  , 'тринадцать'  ,
            'четырнадцать', 'пятнадцать'  ,
            'шестнадцать' , 'семнадцать'  ,
            'восемнадцать', 'девятнадцать'
        ][u]);
    } else {
        if (t > 1) {
            result.push([
                undefined    , undefined  ,
                'двадцать'   , 'тридцать' ,
                'сорок'      , 'пятьдесят',
                'шестьдесят' , 'семьдесят',
                'восемьдесят', 'девяносто'
            ][t]);
        }
        if (u > 0) {
            result.push([
                undefined, 'один' , 'два' , 'три'   , 'четыре',
                'пять'   , 'шесть', 'семь', 'восемь', 'девять'
            ][u]);
        }
    }

    return result.join(' ');
};

const main = () => {
    const number = document.getElementById('number');
    const text = document.getElementById('text');

    number.oninput = () => {
        text.textContent = numberInWords(parseInt(number.value));
    };
};

main();
<label for="name">Число [-999, 999]:</label>
<input type="number" id="number">
<br>
<span id="text">?</span>

▲ 2

Это можно сделать так:

const min = -999,
      max = 999;

// базовый текст чисел
const numberText = {
    "0": "",
    "00": "",
    "1": "один",
    "2": "два",
    "3": "три",
    "4": "четыре",
    "5": "пять",
    "6": "шесть",
    "7": "семь",
    "8": "восемь",
    "9": "девять",
    "10": "десять",
    "11": "одиннадцать",
    "12": "двенадцать",
    "13": "тринадцать",
    "14": "четырнадцать",
    "15": "пятнадцать",
    "16": "шестнадцать",
    "17": "семнадцать",
    "18": "восемнадцать",
    "19": "девятнадцать",
    "20": "двадцать",
    "30": "тридцать",
    "40": "сорок",
    "50": "пятьдесят",
    "60": "шестьдесят",
    "70": "семьдесят",
    "80": "восемьдесят",
    "90": "девяносто",
    "100": "сто",
    "200": "двести",
    "300": "триста",
    "400": "четыреста",
    "500": "пятьсот",
    "600": "шестьсот",
    "700": "семьсот",
    "800": "восемьсот",
    "900": "девятьсот",
};

// добавление поддержки негативных чисел (например, "-1")
for (let key in numberText) {
    numberText["-" + key] = numberText[key];
}

function numberToText(n) {
  // оригинальное число n
  const originalN = n;
  // в эту переменную будет записываться текстовое представление числа
    let stringDigit = "";
    // эта переменная для различных операций с числом, как со строкой
    let nStr = n.toString();
    // преобразование Math.abs(n) для того, чтобы было легче оперировать с числом
    n = Math.abs(n);

    if (nStr.startsWith("-")) {
        // проверяем, чтобы число было в диапазоне, чтобы не получилось "минус "
        stringDigit += (-n >= -999) ? "минус " : ""; // пробел тут обязателен, для того, чтобы текст не слился
        // убираем - (минус) с начала строки nStr
        nStr = nStr.slice(1);
    }

    // тут начинается главное преобразование
    if (n >= 1 && n <= 19) { // если n в диапазоне (1, 19)
      // то просто берём значение с ключом [n] из объекта numberText
        stringDigit += numberText[n];
    } else if (n >= 20 && n <= 99) { // если n в диапазоне (20, 99)
      // то мы сначала берём текстовое представление с первого числа, например, с 26 это будет 20
        stringDigit += numberText[nStr[0] + "0"];
        
        // потом проверяем, если существует цифра, отличное от 0 в конце числа
        if (!n.toString().endsWith("0")) {
          // и если так, то добавляем остаток от числа n % 10, например, с 26 будет 6
            stringDigit += " " + numberText[n % 10];
        }
    } else if (n >= 100 && n <= 999) { // если n в диапазоне (100, 999)
      // сначала добавляем текстовое представление разряда сотен
        stringDigit += numberText[nStr[0] + "00"];
    
    // это переменная для того, чтобы получить разряд десятков
        let twoSignN = (n % 100).toString();

        // проверяем остаток (резряд единиц/десятков), например, если n = 123, то остаток будет 23
        if (twoSignN >= 1 && twoSignN <= 19) { // если разряд десятков в диапазоне (1, 19)
          // добавляем текст разряда десятков 
            stringDigit += " " + numberText[twoSignN];
        } else {
            stringDigit += " " + numberText[twoSignN[0] + "0"];
        }
    
      // если разряд единиц отличный от 0
        if (!nStr.endsWith("0") && (twoSignN >= 20 && twoSignN <= 99)) {
          // то добавляем текстовое представление разряда единиц
            stringDigit += " " + numberText[twoSignN[1]];
        }
    }

  // убрать лишние пробелы в текстовом представлении числа
    stringDigit = stringDigit.replaceAll("  ", " ");
    stringDigit = stringDigit.trim();

    return stringDigit || originalN.toString();
}

Скрипт объяснён в комментариях.

Пример того, как его можно использовать (и демонстрация того, как он работает):

const min=-999,max=999;const numberText={0:"","00":"",1:"один",2:"два",3:"три",4:"четыре",5:"пять",6:"шесть",7:"семь",8:"восемь",9:"девять",10:"десять",11:"одиннадцать",12:"двенадцать",13:"тринадцать",14:"четырнадцать",15:"пятнадцать",16:"шестнадцать",17:"семнадцать",18:"восемнадцать",19:"девятнадцать",20:"двадцать",30:"тридцать",40:"сорок",50:"пятьдесят",60:"шестьдесят",70:"семьдесят",80:"восемьдесят",90:"девяносто",100:"сто",200:"двести",300:"триста",400:"четыреста",500:"пятьсот",600:"шестьсот",700:"семьсот",800:"восемьсот",900:"девятьсот"};for(let key in numberText){numberText["-"+key]=numberText[key]}function numberToText(n){const originalN=n;let stringDigit="";let nStr=n.toString();n=Math.abs(n);if(nStr.startsWith("-")){stringDigit+=-n>=-999?"минус ":"";nStr=nStr.slice(1)}if(n>=1&&n<=19){stringDigit+=numberText[n]}else if(n>=20&&n<=99){stringDigit+=numberText[nStr[0]+"0"];if(!n.toString().endsWith("0")){stringDigit+=" "+numberText[n%10]}}else if(n>=100&&n<=999){stringDigit+=numberText[nStr[0]+"00"];let twoSignN=(n%100).toString();if(twoSignN>=1&&twoSignN<=19){stringDigit+=" "+numberText[twoSignN]}else{stringDigit+=" "+numberText[twoSignN[0]+"0"]}if(!nStr.endsWith("0")&&(twoSignN>=20&&twoSignN<=99)){stringDigit+=" "+numberText[twoSignN[1]]}}stringDigit=stringDigit.replaceAll("  "," ");stringDigit=stringDigit.trim();return stringDigit||originalN.toString()}

let currentNumber = 0;

const numberShowSpan = document.querySelector("#show-number"),
      numberTextShowSpan = document.querySelector("#show-number-text"),
      incrementButton = document.querySelector("#increment"),
      decrementButton = document.querySelector("#decrement");

display();

incrementButton.addEventListener("click", () => {
  currentNumber++;
  display();
});

decrementButton.addEventListener("click", () => {
  currentNumber--;
  display();
});

function display() {
  numberShowSpan.textContent = currentNumber;
  numberTextShowSpan.textContent = numberToText(currentNumber);
}
<p>Текущее число n: <b><span id="show-number">0</span></b></p>
<p>
  Текущее представление числа n в текстовом формате: <b><span id="show-number-text"></span></b>
</p>

<button id="increment">Увеличить</button>/<button id="decrement">Уменьшить</button>

(Первая строка минифицирована для того, чтобы было удобнее читать скрипт демонстрации - для основного скрипта смотрите выше).