[JavaScript Quiz #14] Number Text Representation

Today’s JavaScript quiz is about creating a Number to String utility. Assume that we have the following numbers as an input to our utility:

23
1999
199999
1000000999

Our JavaScript utility should output the following results:

twenty three
one thousand nine hundreds ninety nine
one hundred ninety nine thousand nine hundred ninety nine
one billion nine hundred ninety nine

.
.
.
.
.
.
.
.
.
.
.
.
.
In order to develop this utility, it is important to break-down this problem into small sub-problems and then solve each of them individually. For example, if we wish to print numbers from 0 to 9, this is an easy Job, just create an array that contains the numbers from 0 to 9 and call it digits as follows.

digits = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];

If we want to print numbers from 10 to 19, we can create another array that represents teens as follows:

teens = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];

Then if we want to print numbers from 20 up to 99, we can create another array that represents tys as follows.

tys = ["twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"];

But for numbers from 20 to 99, how can we utilize the previous array for printing their values, if we think little about it, we will find that a number like 39 is about 30 + 9 which will produce at the end "thirty nine". But how to divide a number like 39 to 30 + 9 and get its corresponding text representation, simply this can be done by performing three steps:

  1. Dividing 39 (or generally numbers from 20 to 99) by 10 (Integer Division), and then subtract 2 from the result number in order to pick its text representation "thirty" from its corresponding array (tys array).
  2. Having the mod of 39 (or generally numbers from 20 to 99) and 10 which will give us 9, and then we can get simply pick its text representation "nine" from its corresponding array (digits array).
  3. Finally, augment the two text representations to get the final number text representation which is “thirty nine”.

For numbers from 100 up to 999, For example: 205, we can divide it 205 by 100 to know how many hundred units does it has (2 hundreds) and then have the reminder of this number 205 with 100 which is 5 and “five” representation can be got simply using the previous mentioned procedures. Let’s look into the code which can get the text representation of numbers from 0 to 999.

NumberReader.prototype.readThreeDigitNumber = function(number) { /* 0 ... 999 */
    if (number == 0) {
        return "zero";
    }
    
    var output = "", result, reminder;
    
    if (number > 99) {
        result  = Math.floor(number / 100);
        number = number % 100;
        
        output += this.digits[result] + " hundred";
        
        if (number == 0) {
            return output;
        }
    }
    
    if (number < 10) {
        output = NumberReader.appendToOutput(output, this.digits[number]);    
    } else if (number < 20) {
        output = NumberReader.appendToOutput(output, this.teens[number - 10]);                
    } else {
        result = Math.floor(number / 10);
        reminder = number % 10;
        
        output = NumberReader.appendToOutput(output, this.tys[result - 2]);
        
        if (reminder > 0) {
            output = NumberReader.appendToOutput(output, this.digits[reminder]);
        }
    }
    
    return output;
}

We can apply the same concept with thousands by diving them by 1000 to know the thousands units and having mod with 1000 which can be resolved using the previous procedure. Thankfully, we can apply the same concept with millions and billions as shown below.

NumberReader.prototype.readNumber = function (number) {
    var output = "", result, reminder;
    
    if (number >= 1e9) {
        result = Math.floor(number / 1000000000);
        reminder = number % 1000000000;
        
        output += this.readNumber(result) + " billion " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else if (number >= 1e6 && number < 1e9) {
        result = Math.floor(number / 1000000);
        reminder = number % 1000000;
        
        output += this.readNumber(result) + " million " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else if (number >= 1000 && number < 1e6) {
        result = Math.floor(number / 1000);
        reminder = number % 1000;
        
        output += this.readNumber(result) + " thousand " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else {
        output += this.readThreeDigitNumber(number);
    }
    
    return output;
}

The complete quiz code is shown below.

var NumberReader = function() {
    this.digits = ["zero", "one", "two", "three", "four", "five",
        "six", "seven", "eight", "nine"];

    this.teens = ["ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"];
    
    this.tys = ["twenty", "thirty", "fourty", "fifty", "sixty", "seventy", "eighty", "ninety"];    
}

NumberReader.prototype.readThreeDigitNumber = function(number) { /* 0 ... 999 */
    if (number == 0) {
        return "zero";
    }
    
    var output = "", result, reminder;
    
    if (number > 99) {
        result  = Math.floor(number / 100);
        number = number % 100;
        
        output += this.digits[result] + " hundred";
        
        if (number == 0) {
            return output;
        }
    }
    
    if (number < 10) {
        output = NumberReader.appendToOutput(output, this.digits[number]);    
    } else if (number < 20) {
        output = NumberReader.appendToOutput(output, this.teens[number - 10]);                
    } else {
        result = Math.floor(number / 10);
        reminder = number % 10;
        
        output = NumberReader.appendToOutput(output, this.tys[result - 2]);
        
        if (reminder > 0) {
            output = NumberReader.appendToOutput(output, this.digits[reminder]);
        }
    }
    
    return output;
}

NumberReader.prototype.readNumber = function (number) {
    var output = "", result, reminder;
    
    if (number >= 1e9) {
        result = Math.floor(number / 1000000000);
        reminder = number % 1000000000;
        
        output += this.readNumber(result) + " billion " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else if (number >= 1e6 && number < 1e9) {
        result = Math.floor(number / 1000000);
        reminder = number % 1000000;
        
        output += this.readNumber(result) + " million " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else if (number >= 1000 && number < 1e6) {
        result = Math.floor(number / 1000);
        reminder = number % 1000;
        
        output += this.readNumber(result) + " thousand " + ((reminder > 0) ? this.readNumber(reminder) : "");
    } else {
        output += this.readThreeDigitNumber(number);
    }
    
    return output;
}

NumberReader.appendToOutput = function (output, parameter) {
    if (output == "") {
        output += parameter;
    } else {
        output += " " + parameter;
    }
    
    return output;
}

And this is a test code for NumberReader.

// Test our API ...
var numberReader = new NumberReader();

console.log(numberReader.readNumber(1999999999));
console.log(numberReader.readNumber(1000000999));    
console.log(numberReader.readNumber(100000999));        
console.log(numberReader.readNumber(1000999));
console.log(numberReader.readNumber(199999));
console.log(numberReader.readNumber(100000));
console.log(numberReader.readNumber(1999));    
console.log(numberReader.readNumber(9));        
console.log(numberReader.readNumber(999));        
console.log(numberReader.readNumber(193));
console.log(numberReader.readNumber(23));        
console.log(numberReader.readNumber(333));

The output will be:

one million nine hundred ninety nine
one hundred ninety nine thousand nine hundred ninety nine
one hundred thousand 
one thousand nine hundred ninety nine
nine
nine hundred ninety nine
one hundred ninety three
twenty three
three hundred thirty three
This entry was posted in JavaScript and tagged , , by Hazem Saleh. Bookmark the permalink.

About Hazem Saleh

Hazem Saleh has more than eleven years of experience in Cloud, Mobile and Open Source technologies. He worked as a software engineer, technical leader, application architect, and technical consultant for many clients around the world. He is an Apache PMC (Project Management Committee) member and a person who spent many years of his life writing open source software. Beside being the author of the "JavaScript Unit Testing" book, "JavaScript Mobile Application Development" book, "Pro JSF and HTML5" book and the co-author of the "Definitive guide to Apache MyFaces" book, Hazem is also an author of many technical articles, a developerWorks contributing author and a technical speaker in both local and international conferences such as ApacheCon North America, Geecon, JavaLand, JSFDays, CON-FESS Vienna and JavaOne. Hazem is an XIBMer, he worked in IBM for ten years. Now, He is working for Nickelodeon New York as a Mobile Architect. He is also an OpenGroup Master Certified Specialist.