Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi Team

I am struggling to Create a function that takes a numeral (just digits without separators (e.g. 19093 instead of 19,093) and returns the standard way of reading a number, complete with punctuation using javascript.

What I have tried:

JavaScript
<pre>function numberWithCommas(x) {
    return x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");
}

function test(x, expect) {
    const result = numberWithCommas(x);
    const pass = result === expect;
    console.log(`${pass ? "✓" : "ERROR ====>"} ${x} => ${result}`);
    return pass;
}

let failures = 0;
failures += !test(0,        "0");
failures += !test(100,      "100");
failures += !test(1000,     "1,000");
failures += !test(10000,    "10,000");
failures += !test(100000,   "100,000");
failures += !test(1000000,  "1,000,000");
failures += !test(10000000, "10,000,000");
if (failures) {
    console.log(`${failures} test(s) failed`);
} else {
    console.log("All tests passed");
}
Posted
Updated 23-Feb-23 0:17am

If you take the log10 of a number, what is returned is the number of digits in the number less one as the integer part:
1           0.000
12          1.079
123         2.090
1234        3.091
12345       4.091
123456      5.092
1234567     6.092
12345678    7.092
123456789   8.092
1234567890  9.092
So, if you take the Math.log10()[^] of your value, you can easily work out the length of the string needed. Then it's just a case of extracting digits and inserting them into the string with the appropriate commas - a loop will do it nicely.

Have a think about it, and you'll see what I mean.

Do bear in mind that not all cultures use comma as the separator, or use a "three spacing" format - India for example uses an asymmetric format: "12,34,567"
 
Share this answer
 
v2
Comments
Gcobani Mkontwana 22-Feb-23 20:18pm    
@OriginalGriff can you show me a working example based on what i have written? I cant seem to get this right " FAILED: Expected: 'Zero.', instead got: '0'
FAILED: Expected: 'Eleven.', instead got: '11'
FAILED: Expected: 'Fourteen.', instead got: '14'
FAILED: Expected: 'Fifteen.', instead got: '15'
FAILED: Expected: 'Forty-three.', instead got: '43'
FAILED: Expected: 'Fifty.', instead got: '50'
FAILED:
OriginalGriff 23-Feb-23 0:57am    
I think you have misread the assignment.
I'd go back and read it again - from the error messages you should be returning a text version of the number: "one", "two", "three", ... "one thousand, seven hundred and twenty two", ... instead of "1", "2", "3", "1,722", ...

That's a very different task if so!
* Convert number to string
   * e.g. 1234567 => "1234567"
* Reverse it
   * => "7654321"
* Insert comma after every third char
   * => "765,432,1"
* Reverse it
   * => "1,234,567"


or
Do it in situ: convert to string, keep counting back 3 chars and add comma
e.g. "1234567" => "1234,567" => "1,234,567"
 
Share this answer
 
v2
Comments
Gcobani Mkontwana 22-Feb-23 9:34am    
@jsc42 where according from my function must i convert a number to a string? Must i add another function below the test failure that does this conversion? Please advice and show me, so can i understand you clearly.
OriginalGriff 22-Feb-23 10:37am    
The only format in which you can store a number with "punctuation" is string: numbers do not have a format, it's only applied when you get to the actual presentation to the user - and that's as a string!
If I look at your comments above, it seems that your output should be a conversion of a number to its text representation, you need to write a separate function that performs the conversion. If so, please update your question accordingly as it is a little misleading right now. I ran your code in jsfiddle and it worked fine -
const NUMBER_WORDS = {
    0: "Zero",
    1: "One",
    2: "Two",
    3: "Three",
    4: "Four",
    5: "Five",
    6: "Six",
    7: "Seven",
    8: "Eight",
    9: "Nine",
    10: "Ten",
    11: "Eleven",
    12: "Twelve",
    13: "Thirteen",
    14: "Fourteen",
    15: "Fifteen",
    16: "Sixteen",
    17: "Seventeen",
    18: "Eighteen",
    19: "Nineteen",
    20: "Twenty",
    30: "Thirty",
    40: "Forty",
    50: "Fifty",
    60: "Sixty",
    70: "Seventy",
    80: "Eighty",
    90: "Ninety"
};

function numberToText(n) {
    if (n < 0 || n > 999999999) {
        throw new Error("Number out of range");
    }
    if (n in NUMBER_WORDS) {
        return NUMBER_WORDS[n];
    }
    let text = "";
    if (n >= 1000000) {
        text += numberToText(Math.floor(n / 1000000)) + " Million ";
        n %= 1000000;
    }
    if (n >= 1000) {
        text += numberToText(Math.floor(n / 1000)) + " Thousand ";
        n %= 1000;
    }
    if (n >= 100) {
        text += numberToText(Math.floor(n / 100)) + " Hundred ";
        n %= 100;
    }
    if (n > 0) {
        if (text !== "") {
            text += "and ";
        }
        if (n in NUMBER_WORDS) {
            text += NUMBER_WORDS[n];
        } else {
            text += NUMBER_WORDS[Math.floor(n / 10) * 10] + " ";
            text += NUMBER_WORDS[n % 10];
        }
    }
    return text.trim();
}


To use this function with the input numbers in your above code, you can call numberToText() on each number and log the result to the console -
console.log(numberToText(0));        // "Zero"
console.log(numberToText(100));      // "One Hundred"
console.log(numberToText(1000));     // "One Thousand"
console.log(numberToText(10000));    // "Ten Thousand"
console.log(numberToText(100000));   // "One Hundred Thousand"
console.log(numberToText(1000000));  // "One Million"
console.log(numberToText(10000000)); // "Ten Million"
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900