Last active
October 28, 2020 04:50
-
-
Save steelywing/85fdcbe084c332596179 to your computer and use it in GitHub Desktop.
JavaScript format number
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Format number | |
* | |
* (1234567.8).format(2) | |
* => "1,234,567.80" | |
* | |
* precision: decimal precision | |
*/ | |
// Method 0 (http://stackoverflow.com/a/14428340/1877620) | |
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 | |
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 | |
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(''); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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); | |
// 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)); | |
} | |
// 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 () { | |
var 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(); |
... or replace the function with this one :
Number.prototype.format = function (precision, thousandSep, decimalSep) {
thousandSep = thousandSep || ',';
decimalSep = decimalSep || '.';
if (!isFinite(this)) {
return this.toString();
}
var a = this.toFixed(precision).split('.');
a[0] = a[0].replace(/\d(?=(\d{3})+$)/g, '$&' + thousandSep);
return a.join(decimalSep);
}
I took half a line of your code and it fixed a problem i just faced that when I had let's say 1234 my code converted it to $ 1,234.00 just fine, but when I had 4000, it came off as 4,0.00, so it was shrinking the thousans portion to just 1 zero.
Here's my code just in case:
function formatToMoney(amount) {
return "$ " + amount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",").slice(0, -4);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If we want custom thousands separator or decimal separator, use
replace()
: