Добавим в JavaScript генератор так называемой «суммы прописью», т.е. преобразователь выраженной числом денежной суммы в её словесное представление.
Для этого создадим для объекта Number метод toPhrase(c).
Параметр c задает валюту. Допустимые варианты: RUB (RUR), USD, EUR. По умолчанию c равен RUB.
Number.prototype.toPhrase=function(c)
// сумма прописью для чисел от 0 до 999 триллионов
// можно передать параметр "валюта": RUB,USD,EUR (по умолчанию RUB)
{
var x=this.roundTo(2);
if (x<0 || x>999999999999999.99) return false;
var currency='RUB';
if (typeof(c)=='string')
currency=c.trimAll().toUpperCase();
if (currency=='RUR') currency='RUB';
if (currency!='RUB' && currency!='USD' && currency!='EUR')
return false;
var groups=new Array();
groups[0]=new Array();
groups[1]=new Array();
groups[2]=new Array();
groups[3]=new Array();
groups[4]=new Array();
groups[9]=new Array();
// рубли
// по умолчанию
groups[0][-1]={'RUB': 'рублей', 'USD': 'долларов США', 'EUR': 'евро'};
//исключения
groups[0][1]={'RUB': 'рубль', 'USD': 'доллар США', 'EUR': 'евро'};
groups[0][2]={'RUB': 'рубля', 'USD': 'доллара США', 'EUR': 'евро'};
groups[0][3]={'RUB': 'рубля', 'USD': 'доллара США', 'EUR': 'евро'};
groups[0][4]={'RUB': 'рубля', 'USD': 'доллара США', 'EUR': 'евро'};
// тысячи
// по умолчанию
groups[1][-1]='тысяч';
//исключения
groups[1][1]='тысяча';
groups[1][2]='тысячи';
groups[1][3]='тысячи';
groups[1][4]='тысячи';
// миллионы
// по умолчанию
groups[2][-1]='миллионов';
//исключения
groups[2][1]='миллион';
groups[2][2]='миллиона';
groups[2][3]='миллиона';
groups[2][4]='миллиона';
// миллиарды
// по умолчанию
groups[3][-1]='миллиардов';
//исключения
groups[3][1]='миллиард';
groups[3][2]='миллиарда';
groups[3][3]='миллиарда';
groups[3][4]='миллиарда';
// триллионы
// по умолчанию
groups[4][-1]='триллионов';
//исключения
groups[4][1]='триллион';
groups[4][2]='триллиона';
groups[4][3]='триллиона';
groups[4][4]='триллиона';
// копейки
// по умолчанию
groups[9][-1]={'RUB': 'копеек', 'USD': 'центов', 'EUR': 'центов'};
//исключения
groups[9][1]={'RUB': 'копейка', 'USD': 'цент', 'EUR': 'цент'};
groups[9][2]={'RUB': 'копейки', 'USD': 'цента', 'EUR': 'цента'};
groups[9][3]={'RUB': 'копейки', 'USD': 'цента', 'EUR': 'цента'};
groups[9][4]={'RUB': 'копейки', 'USD': 'цента', 'EUR': 'цента'};
// цифры и числа
// либо просто строка, либо 4 строки в хэше
var names=new Array();
names[1]={0: 'один', 1: 'одна', 2: 'один', 3: 'один', 4: 'один'};
names[2]={0: 'два', 1: 'две', 2: 'два', 3: 'два', 4: 'два'};
names[3]='три';
names[4]='четыре';
names[5]='пять';
names[6]='шесть';
names[7]='семь';
names[8]='восемь';
names[9]='девять';
names[10]='десять';
names[11]='одиннадцать';
names[12]='двенадцать';
names[13]='тринадцать';
names[14]='четырнадцать';
names[15]='пятнадцать';
names[16]='шестнадцать';
names[17]='семнадцать';
names[18]='восемнадцать';
names[19]='девятнадцать';
names[20]='двадцать';
names[30]='тридцать';
names[40]='сорок';
names[50]='пятьдесят';
names[60]='шестьдесят';
names[70]='семьдесят';
names[80]='восемьдесят';
names[90]='девяносто';
names[100]='сто';
names[200]='двести';
names[300]='триста';
names[400]='четыреста';
names[500]='пятьсот';
names[600]='шестьсот';
names[700]='семьсот';
names[800]='восемьсот';
names[900]='девятьсот';
var r='';
var i,j;
var y=Math.floor(x);
// если НЕ ноль рублей
if (y>0)
{
// выделим тройки с руб., тыс., миллионами, миллиардами и триллионами
var t=new Array();
for (i=0;i<=4;i++)
{
t[i]=y%1000;
y=Math.floor(y/1000);
}
var d=new Array();
// выделим в каждой тройке сотни, десятки и единицы
for (i=0;i<=4;i++)
{
d[i]=new Array();
d[i][0]=t[i]%10; // единицы
d[i][10]=t[i]%100-d[i][0]; // десятки
d[i][100]=t[i]-d[i][10]-d[i][0]; // сотни
d[i][11]=t[i]%100; // две правых цифры в виде числа
}
for (i=4; i>=0; i--)
{
if (t[i]>0)
{
if (names[d[i][100]])
r+=' '+ ((typeof(names[d[i][100]])=='object')?(names[d[i][100]][i]):(names[d[i][100]]));
if (names[d[i][11]])
r+=' '+ ((typeof(names[d[i][11]])=='object')?(names[d[i][11]][i]):(names[d[i][11]]));
else
{
if (names[d[i][10]]) r+=' '+ ((typeof(names[d[i][10]])=='object')?(names[d[i][10]][i]):(names[d[i][10]]));
if (names[d[i][0]]) r+=' '+ ((typeof(names[d[i][0]])=='object')?(names[d[i][0]][i]):(names[d[i][0]]));
}
if (names[d[i][11]]) // если существует числительное
j=d[i][11];
else
j=d[i][0];
if (groups[i][j])
{
if (i==0)
r+=' '+groups[i][j][currency];
else
r+=' '+groups[i][j];
}
else
{
if (i==0)
r+=' '+groups[i][-1][currency];
else
r+=' '+groups[i][-1];
}
}
}
if (t[0]==0)
r+=' '+groups[0][-1][currency];
}
else
r='Ноль '+groups[0][-1][currency];
y=((x-Math.floor(x))*100).roundTo();
if (y<10) y='0'+y;
r=r.trimMiddle();
r=r.substr(0,1).toUpperCase()+r.substr(1);
r+=' '+y;
y=y*1;
if (names[y]) // если существует числительное
j=y;
else
j=y%10;
if (groups[9][j])
r+=' '+groups[9][j][currency];
else
r+=' '+groups[9][-1][currency];
return r;
}
В завершение предлагаю испытать работу метода toPhrase().
Введите число x
Введите валюту (RUB, USD, EUR)
x.isFloatStr()
x.toPhrase()
Не забудьте скачать и подключить всю библиотеку, так как метод Number.toPhrase() опирается на некоторые другие методы.
Спасибо!
Похожее решение, есть поддержка украинского языка )
Пожалуйста поделитесь кодом с решением для украинского языка, буду очень признателен!
Отличный код
Уважаемый Valentin, решение впечатляет. Не могли бы Вы подсказать более детально, как все это организовать в форме, сделанной в Adobe Acrobat в формате PDF. Я в программирование JavaScript совсем новичок, но в работе такая вещь пригодится. Если не сложно, пришлите вариант решения на мой E-mail. С уважением, BSI.
Спасибо большое за любезно предоставленный код!
ругается на отсутствующий метод roundTo() 🙁
а, нашел ее в других Ваших постах. спасибо!
Интересный подход.
Самый короткий скрипт всех времен и народов для суммы прописью на русском:
С комментариями!
function sprop(res)
{
// На входе в переменной res должна находиться строка в формате "12345.67" (пример: 18102412990.42)
var h000=[" миллиард", "", "а", "ов", " миллион", "", "а", "ов", " тысяч", "а", "и", "", " рубл", "ь", "я", "ей"];
// Первым идет корень слова, затем окончание для цифры 1, затем для цифер 2-4, затем для всего больше 4 и нуля
var h100=["", "сто", "двести", "триста", "четыреста", "пятьсот", "шестьсот", "семьсот", "восемьсот", "девятьсот"];
var h010=["", "", "двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", "восемьдесят", "девяносто"];
var h011=["", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять", "десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать"];
var pattern="000000000000";
var result=" "+res.substr(res.length-2)+" коп.";// Копируем хвост с копейками в результат "как есть"
res=res.slice(0,res.length-3); // Выкидываем дробную часть с точкой из исходника
res=pattern.substr(res.length-12)+res; // Добавляем в исходник лидирующие нули из pattern
raw = res.split(''); // Разбиваем строку на подстроки, в каждой из которых пока по одной цифре
var p=0, i=0, k=0, t=0; // Переменные
for (var group=0; group1&&t4||t==0){t=3} // Если 0 или 5+ то добавка 3 (единица так и остается добавкой 1)
i=+raw[p]; // Собственно сама цифра (начнем с разряда сотен)
raw[p]=h100[i]; // Заменили сотни (разряд сотен - тупо подстановка)
i=+raw[p+1]; // Разряд десятков: если >=20 - тоже заменяем
if (i>1){raw[p+1]=h010[i]; i=0} // Заменили десятки (двадцать и больше)
k=i*10+(+raw[p+2]); // Считаем индекс K (для массива h011)
if(!isNaN(raw[p+1])){raw[p+1]=""} // Пустоту в десятки если прошлой операцией не заменили на строку
raw[p+2]=h011[k]; // Заменили 0, 1... 9, 10, 11, 12 ... 19
if(group==2&&k==1){raw[p+2]="одна"} // В разряде тысяч один->одна)
if(group==2&&k==2){raw[p+2]="две"} // В разряде тысяч два->две)
if(group==3||(raw[p]+raw[p+1]+raw[p+2]).length>0){ // Если подпись вообще нужна, то... (нужна если "рублей" или непустые триады)
raw[p+2]+=h000[group*4]; // Добавляем подпись к единицам (корень)
raw[p+2]+=h000[group*4+t];} // Добавляем подпись к единицам (окончание)
}
res = raw.join(' ')+result; // Склеиваем строку обратно через пробел и пришиваем обратно дробную часть
res = res.replace(/ +/g," ").trim(); // Убираем двойные пробелы, если вдруг появились, плюс лидирующие и замыкающие
res = res.charAt(0).toUpperCase()+res.slice(1); // Первую букву заглавной
return res; // Для нашего примера: Восемнадцать миллиардов сто два миллиона четыреста двенадцать тысяч девятьсот девяносто рублей 42 коп.
}
Спасибо!
Странно, что в рунете нет достойного кода на эту тему. Желательно, чтобы ваш сайт выпадал первым в списке.
Замечу, что данная функция использует прототипы из прочих статей, приходится искать их отдельно.
Еще увидел, что последняя статья автора датируется 2013 годом. Жив ли блог? Есть ли у вас другой блог/ресурс?
Добрый день.
Огромное спасибо за опубликованный код решения. Вы сэкономили мне несколько рабочих часов.