Pregunta Cómo imprimir un número con comas como separadores de miles en JavaScript


Estoy tratando de imprimir un entero en JavaScript con comas como separadores de miles. Por ejemplo, quiero mostrar el número 1234567 como "1,234,567". ¿Cómo voy a 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;
}

¿Hay una manera más simple o más elegante de hacerlo? Sería bueno si también funciona con flotadores, pero eso no es necesario. No necesita ser específico de la configuración regional para decidir entre puntos y comas.


1165
2018-05-24 23:42


origen


Respuestas:


Usé la idea de la respuesta de Kerry, pero la simplifiqué, ya que solo buscaba algo simple para mi propósito específico. Aquí esta lo que hice:

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

Esto es todo lo que necesitas saber.

@Neils Bom preguntó cómo funciona la expresión regular. Mi explicación es algo larga. No cabe en los comentarios y no sé dónde más ponerlo, así que lo estoy haciendo aquí. Si alguien tiene alguna otra sugerencia sobre dónde colocarla, házmelo saber.

La expresión regular usa 2 aserciones de anticipación: una positiva para buscar cualquier punto en la cadena que tenga un múltiplo de 3 dígitos seguidos y una aserción negativa para asegurarse de que ese punto solo tiene 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 punto a la izquierda del 7 (ya que "789" es un múltiplo de 3 dígitos, "678" es un múltiplo de 3 dígitos, "567", etc.). La aserción negativa verifica que el múltiplo de 3 dígitos no tenga ningún dígito después. "789" tiene un período posterior, por lo que es exactamente un múltiplo de 3 dígitos, por lo que una coma va allí. "678" es un múltiplo de 3 dígitos, pero tiene un "9" después, así que esos 3 dígitos son parte de un grupo de 4, y una coma no va allí. Del mismo modo para "567". "456789" tiene 6 dígitos, que es un múltiplo de 3, por lo que una coma va antes de eso. "345678" es un múltiplo de 3, pero tiene un "9" después, así que no hay coma. Y así. El "\ B" evita que la expresión regular ponga una coma al comienzo 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 usar esta función:

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

2061
2018-05-25 00:40



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

var n = 34523453.345
n.toLocaleString()
"34,523,453.345"

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

Si quieres algo diferente, Numeral.js podría ser interesante


1046
2017-07-15 21:01



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

 Tenga en cuenta que javascript tiene un número máximo valor de 9007199254740991


toLocaleString:

number.toLocaleString(); // "1,234,567,890"

// A more complex example: 
var number2 = 1234.56789; // floating point example
number2.toLocaleString(undefined, {maximumFractionDigits:2}) // "1,234.57"


Formato numérico (Safari No soportado):

var nf = new Intl.NumberFormat();
nf.format(number); // "1,234,567,890"

Por lo que comprobé (al menos Firefox), ambos son más o menos los mismos con respecto al rendimiento.


177
2017-08-22 08:52



Sugiero usar phpjs.org 's formato numérico()

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   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
    // +   improved by: Drew Noakes
    // *     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'
    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 eso incluye pruebas automáticas.

Actualización 26/11/2017

Aquí está el violín como un Stack Snippet con un resultado ligeramente modificado:

function number_format(number, decimals, dec_point, thousands_sep) {
    // http://kevin.vanzonneveld.net
    // +   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
    // +   improved by: Drew Noakes
    // *     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'
    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;
}


86
2018-05-24 23:47



Esta es una variación de la respuesta de @ mikez302, pero modificada para admitir números con decimales (por retroalimentación de @neu-rah que numberWithCommas (12345.6789) -> "12,345.6,789" en lugar de "12,345.6789"

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

65
2018-06-05 15:03



function formatNumber (num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
}

print(formatNumber(2665));      // 2,665
print(formatNumber(102665));    // 102,665
print(formatNumber(111102665)); // 111,102,665

54
2017-08-19 06:47



Gracias a todos por sus respuestas. He desarrollado algunas de las respuestas para hacer una solución más "válida para todos".

El primer fragmento agrega una función que imita PHPes number_format() al prototipo de Número. Si estoy formateando un número, generalmente quiero decimales para que la función tome el número de decimales que se muestran. Algunos países usan comas como decimales y decimales como el separador de miles, por lo que la función permite establecer estos separadores.

Number.prototype.numberFormat = function(decimals, dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.toFixed(decimals).split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousands_sep);

    return parts.join(dec_point);
}

Lo usarías de la siguiente manera:

var foo = 5000;
console.log(foo.numberFormat(2)); // us format: 5,000.00
console.log(foo.numberFormat(2, ',', '.')); // european format: 5.000,00

Descubrí que a menudo necesitaba recuperar el número para operaciones matemáticas, pero parseFloat convierte 5,000 a 5, simplemente tomando la primera secuencia de valores enteros. Así que creé mi propia función de conversión flotante y la agregué al prototipo de cadena.

String.prototype.getFloat = function(dec_point, thousands_sep) {
    dec_point = typeof dec_point !== 'undefined' ? dec_point : '.';
    thousands_sep = typeof thousands_sep !== 'undefined' ? thousands_sep : ',';

    var parts = this.split(dec_point);
    var re = new RegExp("[" + thousands_sep + "]");
    parts[0] = parts[0].replace(re, '');

    return parseFloat(parts.join(dec_point));
}

Ahora puede usar ambas funciones de la siguiente manera:

var foo = 5000;
var fooString = foo.numberFormat(2); // The string 5,000.00
var fooFloat = fooString.getFloat(); // The number 5000;

console.log((fooString.getFloat() + 1).numberFormat(2)); // The string 5,001.00

31
2017-09-18 01:50



Intl.NumberFormat

Función Native JS Compatible con IE11, Edge, Safari, Chrome, Firefox, Opera, Safari en iOS y Chrome en Android.

var number = 3500;

console.log(new Intl.NumberFormat().format(number));
// → '3,500' if in US English locale

28
2017-10-31 23:56



Creo que esta es la expresión regular más corta que lo hace:

/\B(?=(\d{3})+\b)/g

"123456".replace(/\B(?=(\d{3})+\b)/g, ",")

Lo revisé en algunos números y funcionó.


22
2018-03-13 06:31



Number.prototype.toLocaleString() habría sido increíble si fue proporcionado de forma nativa por todos los navegadores (Safari).

Comprobé todas las demás respuestas, pero nadie parecía rellenarlas. Aquí hay una poc hacia eso, que en realidad es una combinación de las dos primeras respuestas; Si toLocaleString funciona si lo usa, si no usa una función personalizada.

var putThousandsSeparators;

putThousandsSeparators = function(value, sep) {
  if (sep == null) {
    sep = ',';
  }
  // check if it needs formatting
  if (value.toString() === value.toLocaleString()) {
    // split decimals
    var parts = value.toString().split('.')
    // format whole numbers
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, sep);
    // put them back together
    value = parts[1] ? parts.join('.') : parts[0];
  } else {
    value = value.toLocaleString();
  }
  return value;
};

alert(putThousandsSeparators(1234567.890));


18
2018-05-19 05:11