Convert digits into words with JavaScript

后端 未结 27 1244
我寻月下人不归
我寻月下人不归 2020-11-22 15:08

I am making a code which converts the given amount into words, heres is what I have got after googling. But I think its a little lengthy code to achieve a simple task. Two R

相关标签:
27条回答
  • 2020-11-22 15:32

    I modified MC Shaman's code to fix the bug of single number having and appear before it

    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)  />

    0 讨论(0)
  • 2020-11-22 15:36

    I like the result I got here which i think is easy to read and short enough to fit as a solution.

    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))

    And the result is :

    eighty-nine trillion seven hundred fifty-four billion six hundred ninety-seven million nine hundred seventy-six thousand four hundred thirty-one

    0 讨论(0)
  • 2020-11-22 15:36

    while this system does use a for loop, It uses US english and is fast, accurate, and expandable(you can add infinite values to the "th" var and they will be included).

    This function grabs the 3 groups of numbers backwards so it can get the number groups where a , would normally separate them in the numeric form. Then each group of three numbers is added to an array with the word form of just the 3 numbers(ex: one hundred twenty three). It then takes that new array list, and reverses it again, while adding the th var of the same index to the end of the string.

    var ones = ['','one ','two ','three ','four ', 'five ','six ','seven ','eight ','nine ','ten ','eleven ','twelve ','thirteen ','fourteen ','fifteen ','sixteen ','seventeen ','eighteen ','nineteen '];
    var tens = ['', '', 'twenty ','thirty ','forty ','fifty ', 'sixty ','seventy ','eighty ','ninety ', 'hundred '];
    var th = ['', 'thousand ','million ','billion ', 'trillion '];
    
    function numberToWord(number){
      var text = "";
      var size = number.length;
    
      var textList = [];
      var textListCount = 0;
    
      //get each 3 digit numbers
      for(var i = number.length-1; i >= 0; i -= 3){
        //get 3 digit group
        var num = 0;
        if(number[(i-2)]){num += number[(i-2)];}
        if(number[(i-1)]){num += number[(i-1)];}
        if(number[i]){num += number[i];}
    
        //remove any extra 0's from begining of number
        num = Math.floor(num).toString();
    
        if(num.length == 1 || num < 20){
          //if one digit or less than 20
          textList[textListCount] = ones[num];
        }else if(num.length == 2){
          //if 2 digits and greater than 20
          textList[textListCount] = tens[num[0]]+ones[num[1]];
        }else if(num.length == 3){
          //if 3 digits
          textList[textListCount] = ones[num[0]]+tens[10]+tens[num[1]]+ones[num[2]];
        }
    
        textListCount++;
    
      }
    
      //add the list of 3 digit groups to the string
      for(var i = textList.length-1; i >= 0; i--){
        if(textList[i] !== ''){text += textList[i]+th[i];} //skip if the number was 0
      }
    
      return text;
    }
    
    0 讨论(0)
  • 2020-11-22 15:37

    Below are the translations from

    • integer to word
    • float to word
    • money to word

    Test cases are at the bottom

    var ONE_THOUSAND = Math.pow(10, 3);
    var ONE_MILLION = Math.pow(10, 6);
    var ONE_BILLION = Math.pow(10, 9);
    var ONE_TRILLION = Math.pow(10, 12);
    var ONE_QUADRILLION = Math.pow(10, 15);
    var ONE_QUINTILLION = Math.pow(10, 18);
    
    function integerToWord(integer) {
      var prefix = '';
      var suffix = '';
    
      if (!integer){ return "zero"; }
      
      if(integer < 0){
        prefix = "negative";
        suffix = integerToWord(-1 * integer);
        return prefix + " " + suffix;
      }
      if(integer <= 90){
        switch (integer) {
          case integer < 0:
            prefix = "negative";
            suffix = integerToWord(-1 * integer);
            return prefix + " "  + suffix;
          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";
          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";
          case 20: return "twenty";
          case 30: return "thirty";
          case 40: return "forty";
          case 50: return "fifty";
          case 60: return "sixty";
          case 70: return "seventy";
          case 80: return "eighty";
          case 90: return "ninety";
          default: break;
        }
      }
    
      if(integer < 100){
        prefix = integerToWord(integer - integer % 10);
        suffix = integerToWord(integer % 10);
        return prefix + "-"  + suffix;
      }
    
      if(integer < ONE_THOUSAND){
        prefix = integerToWord(parseInt(Math.floor(integer / 100), 10) )  + " hundred";
        if (integer % 100){ suffix = " and "  + integerToWord(integer % 100); }
        return prefix + suffix;
      }
    
      if(integer < ONE_MILLION){
        prefix = integerToWord(parseInt(Math.floor(integer / ONE_THOUSAND), 10))  + " thousand";
        if (integer % ONE_THOUSAND){ suffix = integerToWord(integer % ONE_THOUSAND); }
      }
      else if(integer < ONE_BILLION){
        prefix = integerToWord(parseInt(Math.floor(integer / ONE_MILLION), 10))  + " million";
        if (integer % ONE_MILLION){ suffix = integerToWord(integer % ONE_MILLION); }
      }
      else if(integer < ONE_TRILLION){
        prefix = integerToWord(parseInt(Math.floor(integer / ONE_BILLION), 10))  + " billion";
        if (integer % ONE_BILLION){ suffix = integerToWord(integer % ONE_BILLION); }
      }
      else if(integer < ONE_QUADRILLION){
        prefix = integerToWord(parseInt(Math.floor(integer / ONE_TRILLION), 10))  + " trillion";
        if (integer % ONE_TRILLION){ suffix = integerToWord(integer % ONE_TRILLION); }
      }
      else if(integer < ONE_QUINTILLION){
        prefix = integerToWord(parseInt(Math.floor(integer / ONE_QUADRILLION), 10))  + " quadrillion";
        if (integer % ONE_QUADRILLION){ suffix = integerToWord(integer % ONE_QUADRILLION); }
      } else {
        return '';
      }
      return prefix + " "  + suffix;
    }
    
    function moneyToWord(value){
      var decimalValue = (value % 1);
      var integer = value - decimalValue;
      decimalValue = Math.round(decimalValue * 100);
      var decimalText = !decimalValue? '': integerToWord(decimalValue) + ' cent' + (decimalValue === 1? '': 's');
      var integerText= !integer? '': integerToWord(integer) + ' dollar' + (integer === 1? '': 's');
      return (
        integer && !decimalValue? integerText:
        integer && decimalValue? integerText + ' and ' + decimalText:
        !integer && decimalValue? decimalText:
        'zero cents'
      );
    }
    
    function floatToWord(value){
      var decimalValue = (value % 1);
      var integer = value - decimalValue;
      decimalValue = Math.round(decimalValue * 100);
      var decimalText = !decimalValue? '':
        decimalValue < 10? "point o' " + integerToWord(decimalValue):
        decimalValue % 10 === 0? 'point ' + integerToWord(decimalValue / 10):
        'point ' + integerToWord(decimalValue);
      return (
        integer && !decimalValue? integerToWord(integer):
        integer && decimalValue? [integerToWord(integer),  decimalText].join(' '):
        !integer && decimalValue? decimalText:
        integerToWord(0)
      );
    }
    
    // test
    (function(){
      console.log('integerToWord ==================================');
      for(var i = 0; i < 101; ++i){
        console.log('%s=%s', i, integerToWord(i));
      }
      console.log('floatToWord ====================================');
      i = 131;
      while(i--){
        console.log('%s=%s', i / 100, floatToWord(i / 100));
      }
      console.log('moneyToWord ====================================');
      for(i = 0; i < 131; ++i){
        console.log('%s=%s', i / 100, moneyToWord(i / 100));
      }
    }());

    0 讨论(0)
  • 2020-11-22 15:40

    This is in response to @LordZardeck's comment to @naomik's excellent answer above. Sorry, I would've commented directly but I've never posted before so I don't have the privilege to do so, so I am posting here instead.

    Anyhow, I just happened to translate the ES5 version to a more readable form this past weekend so I'm sharing it here. This should be faithful to the original (including the recent edit) and I hope the naming is clear and accurate.

    function int_to_words(int) {
      if (int === 0) return 'zero';
    
      var ONES  = ['','one','two','three','four','five','six','seven','eight','nine','ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen'];
      var TENS  = ['','','twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety'];
      var SCALE = ['','thousand','million','billion','trillion','quadrillion','quintillion','sextillion','septillion','octillion','nonillion'];
    
      // Return string of first three digits, padded with zeros if needed
      function get_first(str) {
        return ('000' + str).substr(-3);
      }
    
      // Return string of digits with first three digits chopped off
      function get_rest(str) {
        return str.substr(0, str.length - 3);
      }
    
      // Return string of triplet convereted to words
      function triplet_to_words(_3rd, _2nd, _1st) {
        return (_3rd == '0' ? '' : ONES[_3rd] + ' hundred ') + (_1st == '0' ? TENS[_2nd] : TENS[_2nd] && TENS[_2nd] + '-' || '') + (ONES[_2nd + _1st] || ONES[_1st]);
      }
    
      // Add to words, triplet words with scale word
      function add_to_words(words, triplet_words, scale_word) {
        return triplet_words ? triplet_words + (scale_word && ' ' + scale_word || '') + ' ' + words : words;
      }
    
      function iter(words, i, first, rest) {
        if (first == '000' && rest.length === 0) return words;
        return iter(add_to_words(words, triplet_to_words(first[0], first[1], first[2]), SCALE[i]), ++i, get_first(rest), get_rest(rest));
      }
    
      return iter('', 0, get_first(String(int)), get_rest(String(int)));
    }
    
    0 讨论(0)
  • 2020-11-22 15:40

    My solution is based on Juan Gaitán's solution for Indian currency, works up to crores.

    function valueInWords(value) {
        let ones = ['', 'one', 'two', 'three', 'four',
                'five', 'six', 'seven', 'eight', 'nine',
                'ten', 'eleven', 'twelve', 'thirteen', 'fourteen',
                'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen'];   
        let tens = ['twenty','thirty', 'forty','fifty', 'sixty', 'seventy', 'eighty', 'ninety'];
        let digit = 0;   
        if (value < 20) return ones[value];   
        if (value < 100) {     
            digit = value % 10; //remainder     
            return tens[Math.floor(value/10)-2] + " " + (digit > 0 ? ones[digit] : "");   
        }
        if (value < 1000) {    
             return ones[Math.floor(value/100)] + " hundred " + (value % 100 > 0 ? valueInWords(value % 100) : "");   
        }   
        if (value < 100000) {     
            return valueInWords(Math.floor(value/1000)) + " thousand " + (value % 1000 > 0 ? valueInWords(value % 1000) : "");   
        }   
        if (value < 10000000) {     
            return valueInWords(Math.floor(value/100000)) + " lakh " + (value % 100000 > 0 ? valueInWords(value % 100000) : "");   
        }   
        return valueInWords(Math.floor(value/10000000)) + " crore " + (value % 10000000 > 0 ? valueInWords(value % 10000000) : ""); 
    }
    
    0 讨论(0)
提交回复
热议问题