Use PHP functions in JavaScript
Can't find a function by "563:563"

JavaScript number_format

Formats a number with grouped thousands

1
2
3
4
56
7
8
9
1011
12
13
14
1516
17
18
19
2021
22
23
24
2526
27
28
29
3031
32
33
34
3536
37
38
39
4041
42
43
44
4546
47
48
49
5051
52
53
54
5556
57
58
59
6061
62
63
64
6566
67
68
69
7071
72
73
function number_format (number, decimals, dec_point, thousands_sep) {
    // Formats a number with grouped thousands  
    // 
    // version: 1109.2015
    // discuss at: http://phpjs.org/functions/number_format    // +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +     bugfix by: Michael White (http://getsprink.com)
    // +     bugfix by: Benjamin Lupton
    // +     bugfix by: Allan Jensen (http://www.winternet.no)    // +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
    // +     bugfix by: Howard Yeend
    // +    revised by: Luke Smith (http://lucassmith.name)
    // +     bugfix by: Diogo Resende
    // +     bugfix by: Rival    // +      input by: Kheang Hok Chin (http://www.distantia.ca/)
    // +   improved by: davook
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +      input by: Jay Klehr
    // +   improved by: Brett Zamir (http://brett-zamir.me)    // +      input by: Amir Habibi (http://www.residence-mixte.com/)
    // +     bugfix by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Theriault
    // +      input by: Amirouche
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)    // *     example 1: number_format(1234.56);
    // *     returns 1: '1,235'
    // *     example 2: number_format(1234.56, 2, ',', ' ');
    // *     returns 2: '1 234,56'
    // *     example 3: number_format(1234.5678, 2, '.', '');    // *     returns 3: '1234.57'
    // *     example 4: number_format(67, 2, ',', '.');
    // *     returns 4: '67,00'
    // *     example 5: number_format(1000);
    // *     returns 5: '1,000'    // *     example 6: number_format(67.311, 2);
    // *     returns 6: '67.31'
    // *     example 7: number_format(1000.55, 1);
    // *     returns 7: '1,000.6'
    // *     example 8: number_format(67000, 5, ',', '.');    // *     returns 8: '67.000,00000'
    // *     example 9: number_format(0.9, 0);
    // *     returns 9: '1'
    // *    example 10: number_format('1.20', 2);
    // *    returns 10: '1.20'    // *    example 11: number_format('1.20', 4);
    // *    returns 11: '1.2000'
    // *    example 12: number_format('1.2000', 3);
    // *    returns 12: '1.200'
    // *    example 13: number_format('1 000,50', 2, '.', ' ');    // *    returns 13: '100 050.00'
    // Strip all characters but numerical ones.
    number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
    var n = !isFinite(+number) ? 0 : +number,
        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
        dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
        s = '',
        toFixedFix = function (n, prec) {
            var k = Math.pow(10, prec);            return '' + Math.round(n * k) / k;
        };
    // Fix for IE parseFloat(0.55).toFixed(0) = 0;
    s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
    if (s[0].length > 3) {        s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
    }
    if ((s[1] || '').length < prec) {
        s[1] = s[1] || '';
        s[1] += new Array(prec - s[1].length + 1).join('0');    }
    return s.join(dec);
}
external links: original PHP docs | raw js source

Examples

» Example 1

Running

1
number_format(1234.56);

Should return

1
'1,235'

» Example 2

Running

1
number_format(1234.56, 2, ',', ' ');

Should return

1
'1 234,56'

Dependencies

No dependencies, you can use this function standalone.

Open syntax issues

php.js uses JsLint to help us keep our code consistent and prevent some common bugs.

Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.


Authors

Thanks to the following developers, you get to have number_format goodness in JavaScript.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Nima
Jan 7th Permalink

q  Thanks , grate job ;)

Gravatar
Koon
29 Sep '11 Permalink

q  Thank you so mush !!

Gravatar
Memo
28 Sep '11 Permalink

q  Me salvo la vida xD
This save my life xD

Gravatar
Sebastian Haller
31 Aug '11 Permalink

q  Sorry, my fix did not work, it should be

s = (prec ? toFixedFix(Math.abs(n), prec) : '' + Math.round(Math.abs(n))).split('.');



and

return (n<0 ? '-' : '')+s.join(dec);


Gravatar
Sebastian Haller
31 Aug '11 Permalink

q  number_format(-5.5) returns -6 in PHP (because PHP rounds half numbers up = away from zero, while JavaScript rounds them always up). Hence I suggest changing line 66 to

s = ((n<0 ? '-' : '') + (prec ? toFixedFix(Math.abs(n), prec) : '' + Math.round(Math.abs(n)))).split('.');



and adding example 14:

// *    example 14: number_format('-5.5');
// *    returns 14: '-6'

Gravatar
Fabricio
2 Aug '11 Permalink

q  Ótimo, foi de grande utilidade, alias, todas as funções são úteis.

Gravatar
Theriault
4 Mar '11 Permalink

q  @WoofWoof: This bug should now be fixed. The new source is available on GitHub, or https://github.com/kvz/phpjs/raw/master/functions/strings/number_format.js

Gravatar
motor
24 Feb '11 Permalink

q  Very well. Thanks you.

Gravatar
bmw sports
22 Dec '10 Permalink

q  This codes makes me dizzy :)

Gravatar
Brett Zamir
15 Dec '10 Permalink

q  @WoofWoof: It does look like a bug. I'm a little busy at the moment unless someone else can help, but in the meantime, you might try money_format() as it can handle larger numbers.

Gravatar
WoofWoof
15 Dec '10 Permalink

q  Nice one!

But I have problem when there's 1,000,000.00... it'll return 0, it is unable to handle such a big sum? only 1000,000.00? I'm relying on this to format $$$... but when dealing with Indonesian Rupiah... which usually of very huge sum.

Gravatar
Kevin van Zonneveld
8 Sep '10 Permalink

q  @ Amirouche: Fixed: https://github.com/kvz/phpjs/commit/3f791fd7fa196ba6a1db6c67c6e8c6f24fc0659b

Gravatar
Amirouche
28 Jul '10 Permalink

q  I can't have this:
number_en = number_format(1 000,50, 2, '.', ' ');

result:

number_en = 1000.50

Gravatar
Kevin van Zonneveld
19 Jun '10 Permalink

q  @ Rafael Martínez: Thanks for taking the time to investigate further. Appreciated

Gravatar
Rafael Martínez
1 Jun '10 Permalink

q  OK, I´m wrong, because, in PHP, the result gives us 555,42 to in number_format(555.425, 2, ',', '.').

I was looking a solution to round like excel.

Anyway my "solution" works fine for "excel´s round".

Greets.

Gravatar
Rafael Martínez
1 Jun '10 Permalink

q  One posible solution. Add

var ajuste = n + 1/(k*10);


and replace the return value for this:

return '' + Math.round(ajuste * k) / k;


in the function toFixedFix declared over the line 50, leave it something like that:

toFixedFix = function (n, prec) {
            var k = Math.pow(10, prec);
            var ajuste = n + 1/(k*10);
            return '' + Math.round(ajuste * k) / k;
        };



Any suggestion??

Gravatar
Rafael Martínez
1 Jun '10 Permalink

q  Hi guys,

I think that I found a bug because I get 555,42 in that function number_format(555.425, 2, ',', '.') when the result could be 555,43

Any solution?

Thanks.

Sorry for my english

Gravatar
Graci Granados
24 Apr '10 Permalink

q  Thanks Brother, congratulation!!!

Gravatar
Brett Zamir
8 Jan '10 Permalink

q  @Ronnie: We're really just focused here on implementing the already-existing API of PHP, and PHP doesn't have any formal way of converting back to a numeric format. Why don't you just transmit both forms together within your application? Or are you depending on user input which may include use of commas, etc.?

If the latter, you might be able to use this:

function strtonumber( str, dec_point, thousands_sep ) {
    // +   based on: http://www.php.net/manual/en/function.number-format.php#76448
    // +      adapted by: Brett Zamir (http://brett-zamir.me)
    // -    depends on: localeconv
    // -    depends on: str_replace
    // *     example 1: strtonumber('1,123.564', '.', ',');
    // *     returns 1: 1123.564
    // *     example 2: strtonumber('1,123', '.', ',')
    // *     returns 2: 1123

    if(typeof dec_point === 'undefined' || typeof thousands_sep === 'undefined') {
        var locale = this.localeconv();
        if(typeof dec_point === 'undefined') {
            dec_point = locale['decimal_point'];
        }
        if(typeof thousands_sep === 'undefined') {
            thousands_sep = locale['thousands_sep'];
        }
    }
    return parseFloat(this.str_replace(dec_point, '.', this.str_replace(thousands_sep, '', str)));
}



I was able to avoid the extra code used in the original (at the end) since JavaScript doesn't represent integers differently from floats as variable types.

Be sure to add the dependencies and also note that localeconv() also has its own dependency of setlocale() which you also will need, at least if you may rely on defaults.

But consider that the default locale set up by setlocale() was based on the default locale I obtained in my own testing which did not include a thousands separator (as one might expect the default to be ',' as English). So, unless you adapt the locale(s) inside setlocale(), you have to specify all of the arguments for strtonumber.

Hope that helps...

Gravatar
Ronnie
7 Jan '10 Permalink

q  I like it, but now I have to calculation on it, so I need to format the number back to a numeric format for example

from
1,000,235.22

to
1000235.22

Gravatar
Robert
2 Jan '10 Permalink

q  thank you! You just made my life 20 times easier.

Gravatar
Kevin van Zonneveld
25 Oct '09 Permalink

q  @ Josh: as you can see this function has been revised 2 times. That means a complete rewrite. I guess what you could blame us for is regression. More specifically: not having a test case for the negative numbers.
But hey, there are over 400 functions we have to maintain and we do all of this for free so please take it or by all means - leave it.

@ Brett Zamir: I chose not to have an incremental version for each function because I felt that could easily lead to inconsistency. Instead it's the shortest form of the modification date that still makes sense.
e.g.: 906.1806 would translate to 20090618 06:00:00

Gravatar
Brett Zamir
11 Oct '09 Permalink

q  @Josh: Although I don't know what Kevin's system of numbering is about exactly, I'm pretty darn sure it wasn't 900 revisions! Please keep in mind that these functions have been posted here by different people, often with submissions which started as mere approximations of the PHP function and over time have had a few bugs fixed, some more PHP behaviors added, etc. Not all of us have the time or experience to review each function in full detail, compare it with PHP behavior and its idiosyncrasies, etc. (and functions earlier on were accepted with more loose standards than now). A lot of functions were added in good faith. We're volunteers just like you are in submitting the patch, only Kevin has done the added work of making a website, a compiler, etc., just in the hopes of it being useful. So, take it or leave it for what it's worth. We'd all love to see a comprehensive review and have the functions put through all of the test cases as used in the PHP source code, but we're not there yet. I think maybe the Duct Tape Programmer philosophy applies to our project: http://www.joelonsoftware.com/items/2009/09/23.html :)

@Andras, Thanks very much for the function. Before Kevin or I get a chance to look at it, could you be sure that it follows the PHP behavior at least as well as the one we have now--passing test cases, etc. and addressing Josh's issue?

Gravatar
Josh
10 Oct '09 Permalink

q  Thank you for the function, however it boggles my mind that you can go through 906 revisions and still can't get negative numbers right (at least in Firefox 3.5.3 or IE 8). Negative numbers are numbers that are less than 0, and yes, they do come into play occasionally in this world. I added a couple changes at the very beginning and end of the function to account for the problem:

[CODE]
//beginning
var prefix = '';
if(number < 0)
prefix = '-';

//end
return prefix + s;

Gravatar
Andras
10 Oct '09 Permalink

q  This is shorter :) Feel free to change var names.

function number_format(amount, nDec, sDec, sTho){
	if (!sDec) sDec = ',';
	if (!sTho) sTho = '.';
	amount = (amount * 1).toFixed(nDec);
	if (isNaN(amount)) return NaN;
	amountExp = (amount + '').split('.');
	amount = amountExp[0];
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(amount)) {
		amount = amount.replace(rgx,'$1' + sTho + '$2');
	};
	if (nDec > 0){
		amount += sDec + amountExp[1];
	};
	return amount;
};


Gravatar
Jay Klehr
19 Jun '09 Permalink

q  Thanks Brett, looks good now.

Gravatar
Brett Zamir
19 Jun '09 Permalink

q  Ok, great, thanks Amir. Fixed and tested (Mozilla). (Also allowed precision 1 to work in all cases.)

Gravatar
Amir Habibi
18 Jun '09 Permalink

q  To continu with Jay's comment, if you try :

number_format('1.2', 2);



You'll still get '1.2' instead of '1.20'

Gravatar
Kevin van Zonneveld
18 Jun '09 Permalink

q  @ Brett Zamir: Thanks for fixing Brett!!

Gravatar
Brett Zamir
18 Jun '09 Permalink

q  Thanks for the report, Jay. Should be fixed now.

Gravatar
Jay Klehr
11 Jun '09 Permalink

q  When using number_format to format numbers used for currency, I noticed that if the number has a single decimal followed by a zero initially, and I apply number_format to it (with 2 decimal precision) I don't get 2 decimals. It strips the trailing zero.

number_format('1.20', 2); // returns 1.2, should return 1.20



Using the above version as of this writing (906.111)

Gravatar
Brett Zamir
1 Jun '09 Permalink

q  @Kheang Hok Chin, thanks for the report and @davook, thanks for the workaround! I've incorporated the workaround (and added some more test cases), and also fixed a problem when the final value was an absolute number and was thus not getting zeroes added. (FYI, the referenced discussion thread was missing a digit at the end: http://forums.mozillazine.org/viewtopic.php?f=9&t=999945 )

Gravatar
davook
25 May '09 Permalink

q  Related to the last comment, i've the same problem.

It seems that "toFixed()" is the problem:
http://forums.mozillazine.org/viewtopic.php?f=9&t=99994

As a temporary, bad and ugly solution i'm using an auxiliar function replacing toFixed().

Example:

// Original code
n.toFixed(prec);

// New code
toFixedFix(n, prec);



The toFixedFix function would be like this:

function toFixedFix(n,prec) {
  var k = Math.pow(10,prec);
  return (Math.round(n*k)/k).toString();
}



Any idea how improve it?

Gravatar
Kheang Hok Chin
22 May '09 Permalink

q  Hi, I have a question in regard to this comment:
- bugfix by: Rival
note 1: For 1000.55 result with precision 1 in FF/Opera is 1,000.5, but in IE is 1,000.6

Has this been fixed or does this mean that if a user using Firefox, Opera, Safari will always get the result 1000.5 when formatting the number 1000.55 to precision 1?

While in IE it returns 1000.6 which is correct as number_format in PHP works the same way.

Is there a fix for this?

Gravatar
Kevin van Zonneveld
15 Feb '09 Permalink

q  @ Rival: Hey there, excellent work Rival! I've also added 2 test cases that cover your findings so we can't make that mistake again. Thanks!

Gravatar
Rival
12 Feb '09 Permalink

q  cleanup
[CODE=&quot;Javascript&quot;]
....
var abs = Math.abs(s);
....
[/CODE]

Gravatar
Rival
12 Feb '09 Permalink

q  - show thousand separator for number=1000
- decimal point for numbers lower than 1000 is undefined

note: for 1000.55 result with precision 1 in FF/Opera is 1,000.5, but in IE is 1,000.6

[CODE=&quot;Javascript&quot;]
function number_format(number, decimals, dec_point, thousands_sep) {
var n = number, prec = decimals;
n = !isFinite(+n) ? 0 : +n;
prec = !isFinite(+prec) ? 0 : Math.abs(prec);
var sep = (typeof thousands_sep == &quot;undefined&quot;) ? ',' : thousands_sep;
var dec = (typeof dec_point == &quot;undefined&quot;) ? '.' : dec_point;

var s = (prec &gt; 0) ? n.toFixed(prec) : Math.round(n).toFixed(prec); //fix for IE parseFloat(0.55).toFixed(0) = 0;

var abs = Math.abs(n).toFixed(prec);
var _, i;

if (abs &gt;= 1000) {
_ = abs.split(/\D/);
i = _[0].length % 3 || 3;

_[0] = s.slice(0,i + (n &lt; 0)) +
_[0].slice(i).replace(/(\d{3})/g, sep+'$1');

s = _.join(dec);
} else {
s = s.replace('.', dec);
}

return s;
}
[/CODE]

Gravatar
Kevin van Zonneveld
2 Feb '09 Permalink

q  @ Diogo Resende: Confirmed. I've processed your fix. Thanks a lot!

Gravatar
Simon
2 Feb '09 Permalink

q  This does not work as is on IE6 and IE7, very simple to fix.

search
is not defined and ie throws an error.

so just add
var search;
to the top of the script.

Gravatar
Diogo Resende
2 Feb '09 Permalink

q  It's not correct for numbers below 1000. It needs an else statement like this:
[CODE=&quot;Javascript&quot;]
if (abs &gt; 1000) {
...
} else {
s = abs.replace('.', ',');
}
[/CODE]

Gravatar
Kevin van Zonneveld
16 Jan '09 Permalink

q  @ Luke: After I changed:

[CODE=&quot;Javascript&quot;]
prec = !isFinite(+prec) ? 2 : Math.abs(prec);
[/CODE]

To

[CODE=&quot;Javascript&quot;]
prec = !isFinite(+prec) ? 0 : Math.abs(prec);
[/CODE]

..All test cases from the php manual worked perfectly. And since your code is a bit easier on the eyes as well, I'll include it in our project. Thanks a lot!

Gravatar
Luke
16 Jan '09 Permalink

q  I attacked the same problem recently and came up with a similar solution
http://gist.github.com/47871

more lines, but fewer characters, and compresses (via YUI Compressor) to about 83% of the version above. Take a look; there may be improvements to be made.

Gravatar
Memiux
15 Jan '09 Permalink

q  Thanks, It's so beautiful and tiny :)

Gravatar
Cees
14 Jan '09 Permalink

q  This was so what I was looking for!!! Thanks, guys!!!

Gravatar
Mariusz
4 Nov '08 Permalink

q  I take it back, got the latest version and all looks good. Thanks to those involved with the fixes!

Gravatar
Mariusz
4 Nov '08 Permalink

q  This method does not seem to work correctly with negative numbers, for example (to 2 decimal places):

-16038 returns: -160,38.00

-820 returns -,820.00

Gravatar
Chad Smith
28 Aug '08 Permalink

q  Ignore my previous comment, I'm an idiot. I was checking to see if it was larger than 1000 before it ran through the function. Duh, sorry.

Love the script!
Chad

Gravatar
Chad Smith
28 Aug '08 Permalink

q  Anyone else notice that if you just put in 1000 it doesn't format the number to 1,000? But if you put in 1001 it formats correctly to 1,001.

Any idea what could make that happen?

Gravatar
Kevin van Zonneveld
8 Jun '08 Permalink

q  @ Howard Yeend: Thanks for noticing. This function was revised, and that reimported a previously fixed bug. It's probably because in some countries (including my own), the dec_point and thou_sep are indeed the other way around compared to the english standard. Anyway. fixed again :)

Gravatar
Howard Yeend
6 Jun '08 Permalink

q  just a comment; aren't the default values for dec_point and thou_sep the wrong way around?

by default it formats 12345.67 as 12.345,67

shouldn't it be 12,345.67 ?


Contribute a New function