Format numbers in JavaScript similar to C#

386,696

Solution 1

Generally

In jQuery

Solution 2

Yes, there is definitely a way to format numbers properly in javascript, for example:

var val=2489.8237

val.toFixed(3) //returns 2489.824 (round up)
val.toFixed(2) //returns 2489.82
val.toFixed(7) //returns 2489.8237000 (padding)

With the use of variablename.toFixed .

And there is another function toPrecision() . For more detail you also can visit

http://raovishal.blogspot.com/2012/01/number-format-in-javascript.html

Solution 3

Here's a simple JS function to add commas to an integer number in string format. It will handle whole numbers or decimal numbers. You can pass it either a number or a string. It obviously returns a string.

function addCommas(str) {
    var parts = (str + "").split("."),
        main = parts[0],
        len = main.length,
        output = "",
        first = main.charAt(0),
        i;

    if (first === '-') {
        main = main.slice(1);
        len = main.length;    
    } else {
        first = "";
    }
    i = len - 1;
    while(i >= 0) {
        output = main.charAt(i) + output;
        if ((len - i) % 3 === 0 && i > 0) {
            output = "," + output;
        }
        --i;
    }
    // put sign back
    output = first + output;
    // put decimal part back
    if (parts.length > 1) {
        output += "." + parts[1];
    }
    return output;
}

Here's a set of test cases: http://jsfiddle.net/jfriend00/6y57j/

You can see it being used in this previous jsFiddle: http://jsfiddle.net/jfriend00/sMnjT/. You can find functions that will handle decimal numbers too with a simple Google search for "javascript add commas".

Converting a number to a string can be done many ways. The easiest is just to add it to a string:

var myNumber = 3;
var myStr = "" + myNumber;   // "3"

Within, the context of your jsFiddle, you'd get commas into the counter by changing this line:

jTarget.text(current);

to this:

jTarget.text(addCommas(current));

You can see it working here: http://jsfiddle.net/jfriend00/CbjSX/

Solution 4

I wrote a simple function (not yet another jQuery plugin needed!!) that converts a number to a decimal separated string or an empty string if the number wasn't a number to begin with:

function format(x) {
    return isNaN(x)?"":x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

format(578999); results in 578,999

format(10); results in 10

if you want to have a decimal point instead of a comma simply replace the comma in the code with a decimal point.

One of the comments correctly stated this only works for integers, with a few small adaptions you can make it work for floating points as well:

function format(x) {
    if(isNaN(x))return "";

    n= x.toString().split('.');
    return n[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",")+(n.length>1?"."+n[1]:"");
}

Solution 5

Here are some solutions, all pass the test suite, test suite and benchmark included, if you want copy and paste to test, try This Gist.

Method 0 (RegExp)

Base on https://stackoverflow.com/a/14428340/1877620, but fix if there is no decimal point.

if (typeof Number.prototype.format === 'undefined') {
    Number.prototype.format = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');
        a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&,');
        return a.join('.');
    }
}

Method 1

if (typeof Number.prototype.format1 === 'undefined') {
    Number.prototype.format1 = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.'),
            // skip the '-' sign
            head = Number(this < 0);

        // skip the digits that's before the first thousands separator 
        head += (a[0].length - head) % 3 || 3;

        a[0] = a[0].slice(0, head) + a[0].slice(head).replace(/\d{3}/g, ',$&');
        return a.join('.');
    };
}

Method 2 (Split to Array)

if (typeof Number.prototype.format2 === 'undefined') {
    Number.prototype.format2 = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('.');

        a[0] = a[0]
            .split('').reverse().join('')
            .replace(/\d{3}(?=\d)/g, '$&,')
            .split('').reverse().join('');

        return a.join('.');
    };
}

Method 3 (Loop)

if (typeof Number.prototype.format3 === 'undefined') {
    Number.prototype.format3 = function (precision) {
        if (!isFinite(this)) {
            return this.toString();
        }

        var a = this.toFixed(precision).split('');
        a.push('.');

        var i = a.indexOf('.') - 3;
        while (i > 0 && a[i-1] !== '-') {
            a.splice(i, 0, ',');
            i -= 3;
        }

        a.pop();
        return a.join('');
    };
}

Example

console.log('======== Demo ========')
var n = 0;
for (var i=1; i<20; i++) {
    n = (n * 10) + (i % 10)/100;
    console.log(n.format(2), (-n).format(2));
}

Separator

If we want custom thousands separator or decimal separator, use replace():

123456.78.format(2).replace(',', ' ').replace('.', ' ');

Test suite

function assertEqual(a, b) {
    if (a !== b) {
        throw a + ' !== ' + b;
    }
}

function test(format_function) {
    console.log(format_function);
    assertEqual('NaN', format_function.call(NaN, 0))
    assertEqual('Infinity', format_function.call(Infinity, 0))
    assertEqual('-Infinity', format_function.call(-Infinity, 0))

    assertEqual('0', format_function.call(0, 0))
    assertEqual('0.00', format_function.call(0, 2))
    assertEqual('1', format_function.call(1, 0))
    assertEqual('-1', format_function.call(-1, 0))
    // decimal padding
    assertEqual('1.00', format_function.call(1, 2))
    assertEqual('-1.00', format_function.call(-1, 2))
    // decimal rounding
    assertEqual('0.12', format_function.call(0.123456, 2))
    assertEqual('0.1235', format_function.call(0.123456, 4))
    assertEqual('-0.12', format_function.call(-0.123456, 2))
    assertEqual('-0.1235', format_function.call(-0.123456, 4))
    // thousands separator
    assertEqual('1,234', format_function.call(1234.123456, 0))
    assertEqual('12,345', format_function.call(12345.123456, 0))
    assertEqual('123,456', format_function.call(123456.123456, 0))
    assertEqual('1,234,567', format_function.call(1234567.123456, 0))
    assertEqual('12,345,678', format_function.call(12345678.123456, 0))
    assertEqual('123,456,789', format_function.call(123456789.123456, 0))
    assertEqual('-1,234', format_function.call(-1234.123456, 0))
    assertEqual('-12,345', format_function.call(-12345.123456, 0))
    assertEqual('-123,456', format_function.call(-123456.123456, 0))
    assertEqual('-1,234,567', format_function.call(-1234567.123456, 0))
    assertEqual('-12,345,678', format_function.call(-12345678.123456, 0))
    assertEqual('-123,456,789', format_function.call(-123456789.123456, 0))
    // thousands separator and decimal
    assertEqual('1,234.12', format_function.call(1234.123456, 2))
    assertEqual('12,345.12', format_function.call(12345.123456, 2))
    assertEqual('123,456.12', format_function.call(123456.123456, 2))
    assertEqual('1,234,567.12', format_function.call(1234567.123456, 2))
    assertEqual('12,345,678.12', format_function.call(12345678.123456, 2))
    assertEqual('123,456,789.12', format_function.call(123456789.123456, 2))
    assertEqual('-1,234.12', format_function.call(-1234.123456, 2))
    assertEqual('-12,345.12', format_function.call(-12345.123456, 2))
    assertEqual('-123,456.12', format_function.call(-123456.123456, 2))
    assertEqual('-1,234,567.12', format_function.call(-1234567.123456, 2))
    assertEqual('-12,345,678.12', format_function.call(-12345678.123456, 2))
    assertEqual('-123,456,789.12', format_function.call(-123456789.123456, 2))
}

console.log('======== Testing ========');
test(Number.prototype.format);
test(Number.prototype.format1);
test(Number.prototype.format2);
test(Number.prototype.format3);

Benchmark

function benchmark(f) {
    var start = new Date().getTime();
    f();
    return new Date().getTime() - start;
}

function benchmark_format(f) {
    console.log(f);
    time = benchmark(function () {
        for (var i = 0; i < 100000; i++) {
            f.call(123456789, 0);
            f.call(123456789, 2);
        }
    });
    console.log(time.format(0) + 'ms');
}

async = [];
function next() {
    setTimeout(function () {
        f = async.shift();
        f && f();
        next();
    }, 10);
}

console.log('======== Benchmark ========');
async.push(function () { benchmark_format(Number.prototype.format); });
async.push(function () { benchmark_format(Number.prototype.format1); });
async.push(function () { benchmark_format(Number.prototype.format2); });
async.push(function () { benchmark_format(Number.prototype.format3); });
next();
Share:
386,696

Related videos on Youtube

xiemails
Author by

xiemails

Updated on May 25, 2020

Comments

  • xiemails
    xiemails about 4 years

    Is there a simple way to format numbers in JavaScript, similar to the formatting methods available in C# (or VB.NET) via ToString("format_provider") or String.Format()?

  • Tomalak
    Tomalak almost 14 years
    A word of warning: The jQuery number formatter you link to (I tried with v1.1.0) is completely broken and useless. As in: It does not work at all. Here is a decent formatting plugin: asual.com/jquery/format
  • blackessej
    blackessej almost 13 years
    thanks for that. Did you view my code on jsfiddle? I basically understand how to convert an integer to a string - what I don't understand, since I'm not very proficient at js yet, is how to do it with the context of the script that I'm using. Any further insights?
  • zatatatata
    zatatatata almost 13 years
    @blackessej I don't understand what has to be appended after a coma. If it's just counting, I'd suggest using float, and if you want 2 decimal places for example, you could simply increment the number by 0.01 each time, not by 1.
  • blackessej
    blackessej almost 13 years
    you'll really have to bear with me - I don't understand how to convert my number to a string within my code.
  • pimvdb
    pimvdb almost 13 years
    Please be sure to use parseInt(..., 10) though, to make sure base 10 is used.
  • jfriend00
    jfriend00 almost 13 years
    @blackessej - I added more onto the end of my answer that shows how addCommas can be added to your fiddle.
  • Brad
    Brad over 12 years
    @Tomalak, You should post that as an answer. That's definitely the best number formatter plugin I've used. I wish there were documentation outside of the unit tests though.
  • Tomalak
    Tomalak over 12 years
    @Brad That's a little late. But good to hear that you've found it useful!
  • Cymen
    Cymen over 12 years
    @Tomalak It's never too late. Here I am looking at this more than a year later!
  • shufler
    shufler almost 12 years
    And me nearly three years later!
  • Maxim Kim
    Maxim Kim almost 12 years
    What about percent formatting? Does asual.com/jquer/format handles it?
  • Prethen
    Prethen over 11 years
    autoNumeric is quite full-featured and recently updated to 1.8.0.
  • user456584
    user456584 over 11 years
    +1 for autoNumeric, though as of this writing (v 1.8.1), input types other than <input> "are NOT supported including HTML 5 number type[s]."
  • user456584
    user456584 over 11 years
    ...And as of that writing, I've discovered "accounting.js" which for many use cases is an even more effective solution.
  • jfriend00
    jfriend00 about 10 years
    Added support for decimal numbers in the addCommas() function so it works for numbers with a decimal part.
  • Tomáš Zato
    Tomáš Zato almost 10 years
    Not an answer to the question. He wants (and so do I) to turn XXXXXXX.YYYY into X,XXX,XXX.YYYY.
  • Tomáš Zato
    Tomáš Zato almost 10 years
    Because I don't want to use library when I just need a simple function...?
  • gavenkoa
    gavenkoa almost 10 years
    Is that simple function: code.google.com/p/javascript-number-formatter/source/browse/‌​… ? I think - yes (60 lines of code).
  • Tomáš Zato
    Tomáš Zato almost 10 years
    You have very properly said "I think". That's because whether something is simple or not is matter of opinion. There is no absolute truth amongst opinions giving us chance to have endless arguments.
  • gavenkoa
    gavenkoa almost 10 years
    This is SO and your behavior is typical among SO users.
  • Tomáš Zato
    Tomáš Zato almost 10 years
    Seems you're really ready to go flaming over my comment. Don't you have anything better to do? Anyway, a one liner cross-country code is (6666.0).toLocaleString(). And you're welcome to call any behavior whatever you want if you're aware that such comments are out of topic and might disappear. Also please stop trying to make me undownvote your post. You're doomed to fail because I didn't downvote it... I prever comments over downvotes.
  • Tomáš Zato
    Tomáš Zato almost 10 years
    Also I agree with your "When downvote write why!". However I'm dissapoined that you actually don't seem to want to know the answer. You just want to argue.
  • gavenkoa
    gavenkoa almost 10 years
    This library pushed to Google code just in time when ECMA-262 5.1 Edition released (June 2011). toLocaleString() is good thing and I don't know about it. Now I understand your arguments. Thanks!
  • patrick
    patrick about 9 years
    If you split the floating point part first, then do this with the integer, and then add the flowing point part again it should also work on fp's
  • Junior Mayhé
    Junior Mayhé over 8 years
    "412.8".replace(/\B(?=(\d{3})+(?!\d))/g, ","); returns 412.8. I think it could return 412.80
  • Kristopher
    Kristopher over 8 years
    Not so hot for negative numbers ):
  • jfriend00
    jfriend00 over 8 years
    @Kristopher - I added support for negative numbers.
  • Kristopher
    Kristopher about 8 years
    Very nice. I'm using this now.
  • Gabriel Graves
    Gabriel Graves over 2 years
    Remember to use === instead of == where you are checking if (decimals == 0) { - it should be if (decimals === 0) {