주어진 양을 단어로 변환하는 코드를 만들고 있습니다. 여기에 인터넷 검색 후 얻은 것입니다. 그러나 나는 간단한 작업을 달성하기 위해 약간 긴 코드라고 생각합니다. 두 개의 정규 표현식과 두 개의 for
루프, 더 간단한 것을 원합니다.
가능한 한 짧게 만들려고합니다. 그리고 내가 생각 해낸 것을 게시 할 것입니다
어떤 제안?
var th = ['','thousand','million', 'billion','trillion'];
var dg = ['zero','one','two','three','four', 'five','six','seven','eight','nine'];
var tn = ['ten','eleven','twelve','thirteen', 'fourteen','fifteen','sixteen', 'seventeen','eighteen','nineteen'];
var tw = ['twenty','thirty','forty','fifty', 'sixty','seventy','eighty','ninety'];
function toWords(s) {
s = s.toString();
s = s.replace(/[\, ]/g,'');
if (s != parseFloat(s)) return 'not a number';
var x = s.indexOf('.');
if (x == -1)
x = s.length;
if (x > 15)
return 'too big';
var n = s.split('');
var str = '';
var sk = 0;
for (var i=0; i < x; i++) {
if ((x-i)%3==2) {
if (n[i] == '1') {
str += tn[Number(n[i+1])] + ' ';
i++;
sk=1;
} else if (n[i]!=0) {
str += tw[n[i]-2] + ' ';
sk=1;
}
} else if (n[i]!=0) { // 0235
str += dg[n[i]] +' ';
if ((x-i)%3==0) str += 'hundred ';
sk=1;
}
if ((x-i)%3==1) {
if (sk)
str += th[(x-i-1)/3] + ' ';
sk=0;
}
}
if (x != s.length) {
var y = s.length;
str += 'point ';
for (var i=x+1; i<y; i++)
str += dg[n[i]] +' ';
}
return str.replace(/\s+/g,' ');
}
또한 위의 코드는 Million / Billion과 같은 영어 번호 체계로 변환되며 남아시아 번호 체계는 원하지 않습니다. Lakhs와 Crores처럼
답변
업데이트 : 생각보다 유용 할 것 같습니다. 방금 npm에 게시했습니다. https://www.npmjs.com/package/num-words
다음은 더 짧은 코드입니다. 하나의 RegEx와 루프가 없습니다. 남아시아 번호 체계에서 원하는대로 변환합니다.
var a = ['','one ','two ','three ','four ', 'five ','six ','seven ','eight ','nine ','ten ','eleven ','twelve ','thirteen ','fourteen ','fifteen ','sixteen ','seventeen ','eighteen ','nineteen '];
var b = ['', '', 'twenty','thirty','forty','fifty', 'sixty','seventy','eighty','ninety'];
function inWords (num) {
if ((num = num.toString()).length > 9) return 'overflow';
n = ('000000000' + num).substr(-9).match(/^(\d{2})(\d{2})(\d{2})(\d{1})(\d{2})$/);
if (!n) return; var str = '';
str += (n[1] != 0) ? (a[Number(n[1])] || b[n[1][0]] + ' ' + a[n[1][1]]) + 'crore ' : '';
str += (n[2] != 0) ? (a[Number(n[2])] || b[n[2][0]] + ' ' + a[n[2][1]]) + 'lakh ' : '';
str += (n[3] != 0) ? (a[Number(n[3])] || b[n[3][0]] + ' ' + a[n[3][1]]) + 'thousand ' : '';
str += (n[4] != 0) ? (a[Number(n[4])] || b[n[4][0]] + ' ' + a[n[4][1]]) + 'hundred ' : '';
str += (n[5] != 0) ? ((str != '') ? 'and ' : '') + (a[Number(n[5])] || b[n[5][0]] + ' ' + a[n[5][1]]) + 'only ' : '';
return str;
}
document.getElementById('number').onkeyup = function () {
document.getElementById('words').innerHTML = inWords(document.getElementById('number').value);
};
<span id="words"></span>
<input id="number" type="text" />
유일한 제한은 최대 9 자리까지 변환 할 수 있다는 것입니다. 대부분의 경우 충분하다고 생각합니다.
답변
” 믿을 수 없을 정도로 간단한 작업.” – 감자 튀김
과연. 이 문제의 세부 사항에는 많은 작은 악마가 있습니다. tho를 해결하는 것은 매우 재미있었습니다.
편집 : 이 업데이트는 훨씬 더 구성적인 접근 방식을 취합니다. 이전에는 몇 가지 다른 독점 기능을 감싸는 하나의 큰 기능이있었습니다. 대신, 이번에는 다양한 작업에 사용할 수있는 일반적인 재사용 가능한 함수를 정의합니다. 우리가 numToWords
그 자체를 살펴본 후 그에 대한 더 많은 것…
// numToWords :: (Number a, String a) => a -> String
let numToWords = n => {
let a = [
'', 'one', 'two', 'three', 'four',
'five', 'six', 'seven', 'eight', 'nine',
'ten', 'eleven', 'twelve', 'thirteen', 'fourteen',
'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'
];
let b = [
'', '', 'twenty', 'thirty', 'forty',
'fifty', 'sixty', 'seventy', 'eighty', 'ninety'
];
let g = [
'', 'thousand', 'million', 'billion', 'trillion', 'quadrillion',
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion'
];
// this part is really nasty still
// it might edit this again later to show how Monoids could fix this up
let makeGroup = ([ones,tens,huns]) => {
return [
num(huns) === 0 ? '' : a[huns] + ' hundred ',
num(ones) === 0 ? b[tens] : b[tens] && b[tens] + '-' || '',
a[tens+ones] || a[ones]
].join('');
};
// "thousands" constructor; no real good names for this, i guess
let thousand = (group,i) => group === '' ? group : `${group} ${g[i]}`;
// execute !
if (typeof n === 'number') return numToWords(String(n));
if (n === '0') return 'zero';
return comp (chunk(3)) (reverse) (arr(n))
.map(makeGroup)
.map(thousand)
.filter(comp(not)(isEmpty))
.reverse()
.join(' ');
};
종속성은 다음과 같습니다.
의도가 즉시 명확하기 때문에 문서가 필요하지 않음을 알 수 있습니다. chunk
소화하는 데 시간이 걸리는 유일한 사람 일 수도 있지만 그렇게 나쁘지는 않습니다. 게다가 함수 이름은 그것이 무엇을하는지 꽤 좋은 지표를 제공하며 아마도 우리가 전에 만난 함수일 것입니다.
const arr = x => Array.from(x);
const num = x => Number(x) || 0;
const str = x => String(x);
const isEmpty = xs => xs.length === 0;
const take = n => xs => xs.slice(0,n);
const drop = n => xs => xs.slice(n);
const reverse = xs => xs.slice(0).reverse();
const comp = f => g => x => f (g (x));
const not = x => !x;
const chunk = n => xs =>
isEmpty(xs) ? [] : [take(n)(xs), ...chunk (n) (drop (n) (xs))];
“그래서 이것들이 더 나아질까요?”
코드가 어떻게 크게 정리되었는지 살펴보십시오.
// NEW CODE (truncated)
return comp (chunk(3)) (reverse) (arr(n))
.map(makeGroup)
.map(thousand)
.filter(comp(not)(isEmpty))
.reverse()
.join(' ');
// OLD CODE (truncated)
let grp = n => ('000' + n).substr(-3);
let rem = n => n.substr(0, n.length - 3);
let cons = xs => x => g => x ? [x, g && ' ' + g || '', ' ', xs].join('') : xs;
let iter = str => i => x => r => {
if (x === '000' && r.length === 0) return str;
return iter(cons(str)(fmt(x))(g[i]))
(i+1)
(grp(r))
(rem(r));
};
return iter('')(0)(grp(String(n)))(rem(String(n)));
가장 중요한 것은 새 코드에 추가 한 유틸리티 함수를 앱의 다른 위치에서 사용할 수 있다는 것입니다. 이것은 numToWords
이러한 방식 으로 구현하는 부작용 으로 다른 기능을 무료로 얻을 수 있음을 의미합니다 . 보너스 소다!
일부 테스트
console.log(numToWords(11009));
//=> eleven thousand nine
console.log(numToWords(10000001));
//=> ten million one
console.log(numToWords(987));
//=> nine hundred eighty-seven
console.log(numToWords(1015));
//=> one thousand fifteen
console.log(numToWords(55111222333));
//=> fifty-five billion one hundred eleven million two hundred
// twenty-two thousand three hundred thirty-three
console.log(numToWords("999999999999999999999991"));
//=> nine hundred ninety-nine sextillion nine hundred ninety-nine
// quintillion nine hundred ninety-nine quadrillion nine hundred
// ninety-nine trillion nine hundred ninety-nine billion nine
// hundred ninety-nine million nine hundred ninety-nine thousand
// nine hundred ninety-one
console.log(numToWords(6000753512));
//=> six billion seven hundred fifty-three thousand five hundred
// twelve
실행 가능한 데모
답변
나는 이것에 대한 더 나은 솔루션을 개발하는 데 시간을 보냈습니다. 매우 큰 숫자를 처리 할 수 있지만 16 자리가 넘으면 숫자를 문자열로 전달합니다. JavaScript 수의 한계에 관한 것.
function numberToEnglish( n ) {
var string = n.toString(), units, tens, scales, start, end, chunks, chunksLen, chunk, ints, i, word, words, and = 'and';
/* Remove spaces and commas */
string = string.replace(/[, ]/g,"");
/* Is number zero? */
if( parseInt( string ) === 0 ) {
return 'zero';
}
/* Array of units as words */
units = [ '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen' ];
/* Array of tens as words */
tens = [ '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety' ];
/* Array of scales as words */
scales = [ '', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quatttuor-decillion', 'quindecillion', 'sexdecillion', 'septen-decillion', 'octodecillion', 'novemdecillion', 'vigintillion', 'centillion' ];
/* Split user argument into 3 digit chunks from right to left */
start = string.length;
chunks = [];
while( start > 0 ) {
end = start;
chunks.push( string.slice( ( start = Math.max( 0, start - 3 ) ), end ) );
}
/* Check if function has enough scale words to be able to stringify the user argument */
chunksLen = chunks.length;
if( chunksLen > scales.length ) {
return '';
}
/* Stringify each integer in each chunk */
words = [];
for( i = 0; i < chunksLen; i++ ) {
chunk = parseInt( chunks[i] );
if( chunk ) {
/* Split chunk into array of individual integers */
ints = chunks[i].split( '' ).reverse().map( parseFloat );
/* If tens integer is 1, i.e. 10, then add 10 to units integer */
if( ints[1] === 1 ) {
ints[0] += 10;
}
/* Add scale word if chunk is not zero and array item exists */
if( ( word = scales[i] ) ) {
words.push( word );
}
/* Add unit word if array item exists */
if( ( word = units[ ints[0] ] ) ) {
words.push( word );
}
/* Add tens word if array item exists */
if( ( word = tens[ ints[1] ] ) ) {
words.push( word );
}
/* Add 'and' string after units or tens integer if: */
if( ints[0] || ints[1] ) {
/* Chunk has a hundreds integer or chunk is the first of multiple chunks */
if( ints[2] || ! i && chunksLen ) {
words.push( and );
}
}
/* Add hundreds word if array item exists */
if( ( word = units[ ints[2] ] ) ) {
words.push( word + ' hundred' );
}
}
}
return words.reverse().join( ' ' );
}
// - - - - - Tests - - - - - -
function test(v) {
var sep = ('string'==typeof v)?'"':'';
console.log("numberToEnglish("+sep + v.toString() + sep+") = "+numberToEnglish(v));
}
test(2);
test(721);
test(13463);
test(1000001);
test("21,683,200,000,621,384");
답변
재귀 적으로 시도해 볼 수 있습니다. 0에서 999999 사이의 숫자에 대해 작동합니다. (~~) 는 Math.floor와 동일합니다.
var num = "zero one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen".split(" ");
var tens = "twenty thirty forty fifty sixty seventy eighty ninety".split(" ");
function number2words(n){
if (n < 20) return num[n];
var digit = n%10;
if (n < 100) return tens[~~(n/10)-2] + (digit? "-" + num[digit]: "");
if (n < 1000) return num[~~(n/100)] +" hundred" + (n%100 == 0? "": " " + number2words(n%100));
return number2words(~~(n/1000)) + " thousand" + (n%1000 != 0? " " + number2words(n%1000): "");
}
답변
나는 내가 여기에서 얻은 결과가 마음에 듭니다. 읽기 쉽고 짧아서 해결책으로 적합합니다.
function NumInWords (number) {
const first = ['','one ','two ','three ','four ', 'five ','six ','seven ','eight ','nine ','ten ','eleven ','twelve ','thirteen ','fourteen ','fifteen ','sixteen ','seventeen ','eighteen ','nineteen '];
const tens = ['', '', 'twenty','thirty','forty','fifty', 'sixty','seventy','eighty','ninety'];
const mad = ['', 'thousand', 'million', 'billion', 'trillion'];
let word = '';
for (let i = 0; i < mad.length; i++) {
let tempNumber = number%(100*Math.pow(1000,i));
if (Math.floor(tempNumber/Math.pow(1000,i)) !== 0) {
if (Math.floor(tempNumber/Math.pow(1000,i)) < 20) {
word = first[Math.floor(tempNumber/Math.pow(1000,i))] + mad[i] + ' ' + word;
} else {
word = tens[Math.floor(tempNumber/(10*Math.pow(1000,i)))] + '-' + first[Math.floor(tempNumber/Math.pow(1000,i))%10] + mad[i] + ' ' + word;
}
}
tempNumber = number%(Math.pow(1000,i+1));
if (Math.floor(tempNumber/(100*Math.pow(1000,i))) !== 0) word = first[Math.floor(tempNumber/(100*Math.pow(1000,i)))] + 'hunderd ' + word;
}
return word;
}
console.log(NumInWords(89754697976431))
결과는 다음과 같습니다.
88 조 7 백오 십사 십억 육백 구십 칠백 만 구백 칠십 육천 사백 삼십일
답변
<html>
<head>
<title>HTML - Convert numbers to words using JavaScript</title>
<script type="text/javascript">
function onlyNumbers(evt) {
var e = event || evt; // For trans-browser compatibility
var charCode = e.which || e.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57))
return false;
return true;
}
function NumToWord(inputNumber, outputControl) {
var str = new String(inputNumber)
var splt = str.split("");
var rev = splt.reverse();
var once = ['Zero', ' One', ' Two', ' Three', ' Four', ' Five', ' Six', ' Seven', ' Eight', ' Nine'];
var twos = ['Ten', ' Eleven', ' Twelve', ' Thirteen', ' Fourteen', ' Fifteen', ' Sixteen', ' Seventeen', ' Eighteen', ' Nineteen'];
var tens = ['', 'Ten', ' Twenty', ' Thirty', ' Forty', ' Fifty', ' Sixty', ' Seventy', ' Eighty', ' Ninety'];
numLength = rev.length;
var word = new Array();
var j = 0;
for (i = 0; i < numLength; i++) {
switch (i) {
case 0:
if ((rev[i] == 0) || (rev[i + 1] == 1)) {
word[j] = '';
}
else {
word[j] = '' + once[rev[i]];
}
word[j] = word[j];
break;
case 1:
aboveTens();
break;
case 2:
if (rev[i] == 0) {
word[j] = '';
}
else if ((rev[i - 1] == 0) || (rev[i - 2] == 0)) {
word[j] = once[rev[i]] + " Hundred ";
}
else {
word[j] = once[rev[i]] + " Hundred and";
}
break;
case 3:
if (rev[i] == 0 || rev[i + 1] == 1) {
word[j] = '';
}
else {
word[j] = once[rev[i]];
}
if ((rev[i + 1] != 0) || (rev[i] > 0)) {
word[j] = word[j] + " Thousand";
}
break;
case 4:
aboveTens();
break;
case 5:
if ((rev[i] == 0) || (rev[i + 1] == 1)) {
word[j] = '';
}
else {
word[j] = once[rev[i]];
}
if (rev[i + 1] !== '0' || rev[i] > '0') {
word[j] = word[j] + " Lakh";
}
break;
case 6:
aboveTens();
break;
case 7:
if ((rev[i] == 0) || (rev[i + 1] == 1)) {
word[j] = '';
}
else {
word[j] = once[rev[i]];
}
if (rev[i + 1] !== '0' || rev[i] > '0') {
word[j] = word[j] + " Crore";
}
break;
case 8:
aboveTens();
break;
// This is optional.
// case 9:
// if ((rev[i] == 0) || (rev[i + 1] == 1)) {
// word[j] = '';
// }
// else {
// word[j] = once[rev[i]];
// }
// if (rev[i + 1] !== '0' || rev[i] > '0') {
// word[j] = word[j] + " Arab";
// }
// break;
// case 10:
// aboveTens();
// break;
default: break;
}
j++;
}
function aboveTens() {
if (rev[i] == 0) { word[j] = ''; }
else if (rev[i] == 1) { word[j] = twos[rev[i - 1]]; }
else { word[j] = tens[rev[i]]; }
}
word.reverse();
var finalOutput = '';
for (i = 0; i < numLength; i++) {
finalOutput = finalOutput + word[i];
}
document.getElementById(outputControl).innerHTML = finalOutput;
}
</script>
</head>
<body>
<h1>
HTML - Convert numbers to words using JavaScript</h1>
<input id="Text1" type="text" onkeypress="return onlyNumbers(this.value);" onkeyup="NumToWord(this.value,'divDisplayWords');"
maxlength="9" style="background-color: #efefef; border: 2px solid #CCCCC; font-size: large" />
<br />
<br />
<div id="divDisplayWords" style="font-size: 13; color: Teal; font-family: Arial;">
</div>
</body>
</html>
답변
MC Shaman의 코드를 수정하여 단일 숫자가 있고 그 앞에 나타나는 버그를 수정했습니다.
function numberToEnglish( n ) {
var string = n.toString(), units, tens, scales, start, end, chunks, chunksLen, chunk, ints, i, word, words, and = 'and';
/* Remove spaces and commas */
string = string.replace(/[, ]/g,"");
/* Is number zero? */
if( parseInt( string ) === 0 ) {
return 'zero';
}
/* Array of units as words */
units = [ '', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen' ];
/* Array of tens as words */
tens = [ '', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety' ];
/* Array of scales as words */
scales = [ '', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quatttuor-decillion', 'quindecillion', 'sexdecillion', 'septen-decillion', 'octodecillion', 'novemdecillion', 'vigintillion', 'centillion' ];
/* Split user argument into 3 digit chunks from right to left */
start = string.length;
chunks = [];
while( start > 0 ) {
end = start;
chunks.push( string.slice( ( start = Math.max( 0, start - 3 ) ), end ) );
}
/* Check if function has enough scale words to be able to stringify the user argument */
chunksLen = chunks.length;
if( chunksLen > scales.length ) {
return '';
}
/* Stringify each integer in each chunk */
words = [];
for( i = 0; i < chunksLen; i++ ) {
chunk = parseInt( chunks[i] );
if( chunk ) {
/* Split chunk into array of individual integers */
ints = chunks[i].split( '' ).reverse().map( parseFloat );
/* If tens integer is 1, i.e. 10, then add 10 to units integer */
if( ints[1] === 1 ) {
ints[0] += 10;
}
/* Add scale word if chunk is not zero and array item exists */
if( ( word = scales[i] ) ) {
words.push( word );
}
/* Add unit word if array item exists */
if( ( word = units[ ints[0] ] ) ) {
words.push( word );
}
/* Add tens word if array item exists */
if( ( word = tens[ ints[1] ] ) ) {
words.push( word );
}
/* Add 'and' string after units or tens integer if: */
if( ints[0] || ints[1] ) {
/* Chunk has a hundreds integer or chunk is the first of multiple chunks */
if( ints[2] || (i + 1) > chunksLen ) {
words.push( and );
}
}
/* Add hundreds word if array item exists */
if( ( word = units[ ints[2] ] ) ) {
words.push( word + ' hundred' );
}
}
}
return words.reverse().join( ' ' );
}
// - - - - - Tests - - - - - -
function figure(val) {
finalFig = numberToEnglish(val);
document.getElementById("words").innerHTML = finalFig;
}
<span id="words"></span>
<input id="number" type="text" onkeyup=figure(this.value) />