¿Cómo formatear un número con comas como separadores de miles?

Resuelto Elias Zamaria asked hace 14 años • 52 respuestas

Estoy intentando imprimir un número entero en JavaScript con comas como separadores de miles. Por ejemplo, quiero mostrar el número 1234567 como "1.234.567". ¿Cómo haría para hacer esto?

Así es como lo estoy haciendo:

function numberWithCommas(x) {
    x = x.toString();
    var pattern = /(-?\d+)(\d{3})/;
    while (pattern.test(x))
        x = x.replace(pattern, "$1,$2");
    return x;
}

console.log(numberWithCommas(1000))
Expandir fragmento

¿Existe una forma más sencilla o más elegante de hacerlo? Sería bueno que también funcionara con flotadores, pero eso no es necesario. No es necesario que sea específico de la región para decidir entre puntos y comas.

Elias Zamaria avatar May 25 '10 06:05 Elias Zamaria
Aceptado

Utilicé la idea de la respuesta de Kerry, pero la simplifiqué ya que solo buscaba algo simple para mi propósito específico. Esto es lo que tengo:

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

Mostrar fragmento de código


La expresión regular utiliza 2 afirmaciones anticipadas:

  • uno positivo para buscar cualquier punto en la cadena que tenga un múltiplo de 3 dígitos seguidos después,
  • una afirmación negativa para asegurarse de que ese punto solo tenga exactamente un múltiplo de 3 dígitos. La expresión de reemplazo pone una coma allí.

Por ejemplo, si lo pasa 123456789.01, la afirmación positiva coincidirá con cada lugar a la izquierda del 7 (ya que 789es múltiplo de 3 dígitos, 678es múltiplo de 3 dígitos, 567etc.). La afirmación negativa verifica que el múltiplo de 3 dígitos no tenga ningún dígito después. 789tiene un punto después, por lo que es exactamente un múltiplo de 3 dígitos, por lo que va una coma allí. 678es un múltiplo de 3 dígitos pero tiene un 9después, por lo que esos 3 dígitos son parte de un grupo de 4 y la coma no va allí. De manera similar para 567. 456789tiene 6 dígitos, que es múltiplo de 3, por lo que va una coma antes. 345678es un múltiplo de 3, pero tiene un 9después, por lo que no va ninguna coma allí. Etcétera. Esto \Bevita que la expresión regular ponga una coma al principio de la cadena.

@ neu-rah mencionó que esta función agrega comas en lugares no deseados si hay más de 3 dígitos después del punto decimal. Si esto es un problema, puede utilizar esta función:

function numberWithCommas(x) {
    var parts = x.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
}

Mostrar fragmento de código

@tjcrowder señaló que ahora que JavaScript tiene búsqueda hacia atrás ( información de soporte ), se puede resolver en la propia expresión regular :

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

Mostrar fragmento de código

(?<!\.\d*)es una mirada hacia atrás negativa que dice que la coincidencia no puede ir precedida por un .seguido de cero o más dígitos. La mirada hacia atrás negativa es más rápida que la solución splity ( comparación ), al menos en V8.join

Elias Zamaria avatar May 25 '2010 00:05 Elias Zamaria

Me sorprende que nadie haya mencionado Number.prototype.toLocaleString . Está implementado en JavaScript 1.5 (que se introdujo en 1999), por lo que básicamente es compatible con todos los principales navegadores.

var n = 34523453.345;
console.log(n.toLocaleString());    // "34,523,453.345"
Expandir fragmento

También funciona en Node.js a partir de v0.12 mediante la inclusión de Intl

Si quieres algo diferente, Numeral.js puede resultar interesante.

uKolka avatar Jul 15 '2013 21:07 uKolka

A continuación se muestran dos API de navegador diferentes que pueden transformar números en cadenas estructuradas . Tenga en cuenta que no todas las máquinas de los usuarios tienen una configuración regional que utiliza comas entre números . Para imponer comas en la salida, se puede utilizar cualquier configuración regional "occidental" , comoen-US

let number = 1234567890; // Example number to be converted

⚠️ Tenga en cuenta que javascript tiene un valor entero máximo de9007199254740991


// default behaviour on a machine with a locale that uses commas for numbers
let number = 1234567890;
number.toLocaleString(); // "1,234,567,890"

// With custom settings, forcing a "US" locale to guarantee commas in output
let number2 = 1234.56789; // floating point example
number2.toLocaleString('en-US', {maximumFractionDigits:2}); // "1,234.57"

//You can also force a minimum of 2 trailing digits
let number3 = 1.5;
number3.toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2}); //"1.50"

Formato numérico

let number = 1234567890;
let nf = new Intl.NumberFormat('en-US');
nf.format(number); // "1,234,567,890"

Por lo que verifiqué (al menos Firefox), ambos son más o menos iguales en cuanto a rendimiento.

Demostración en vivo : https://codepen.io/vsync/pen/MWjdbgL?editors=1000

vsync avatar Aug 22 '2015 08:08 vsync

Sugiero usar number_format() de phpjs.org

function number_format(number, decimals, dec_point, thousands_sep) {
    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,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().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);
}

ACTUALIZACIÓN 13/02/14

La gente ha estado informando que esto no funciona como se esperaba, así que hice un JS Fiddle que incluye pruebas automatizadas.

Actualización 26/11/2017

Aquí está ese violín como un fragmento de pila con una salida ligeramente modificada:

function number_format(number, decimals, dec_point, thousands_sep) {
    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,
        toFixedFix = function (n, prec) {
            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
            var k = Math.pow(10, prec);
            return Math.round(n * k) / k;
        },
        s = (prec ? toFixedFix(n, prec) : Math.round(n)).toString().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);
}

var exampleNumber = 1;
function test(expected, number, decimals, dec_point, thousands_sep)
{
    var actual = number_format(number, decimals, dec_point, thousands_sep);
    console.log(
        'Test case ' + exampleNumber + ': ' +
        '(decimals: ' + (typeof decimals === 'undefined' ? '(default)' : decimals) +
        ', dec_point: "' + (typeof dec_point === 'undefined' ? '(default)' : dec_point) + '"' +
        ', thousands_sep: "' + (typeof thousands_sep === 'undefined' ? '(default)' : thousands_sep) + '")'
    );
    console.log('  => ' + (actual === expected ? 'Passed' : 'FAILED') + ', got "' + actual + '", expected "' + expected + '".');
    exampleNumber++;
}

test('1,235',    1234.56);
test('1 234,56', 1234.56, 2, ',', ' ');
test('1234.57',  1234.5678, 2, '.', '');
test('67,00',    67, 2, ',', '.');
test('1,000',    1000);
test('67.31',    67.311, 2);
test('1,000.6',  1000.55, 1);
test('67.000,00000', 67000, 5, ',', '.');
test('1',        0.9, 0);
test('1.20',     '1.20', 2);
test('1.2000',   '1.20', 4);
test('1.200',    '1.2000', 3);
.as-console-wrapper {
  max-height: 100% !important;
}
Expandir fragmento

Kerry Jones avatar May 24 '2010 23:05 Kerry Jones