Separador de milhar Javascript / formato de string [duplicado]

96

Existe alguma função em Javascript para formatar números e strings?

Estou procurando uma forma de separador de milhar para string ou números ... (como String.Format In c #)

LostLord
fonte
Acho que você encontrará o que precisa lá :) stackoverflow.com/questions/610406/…
Jad de
How to print a number with commas as thousands separators in JavaScript: stackoverflow.com/questions/2901102/…
Adrien Be

Respostas:

159

Atualização (7 anos depois)

A referência citada na resposta original abaixo estava errada. Não é construído em uma função para isso, que é exatamente o kaiser sugere a seguir:toLocaleString

Então você pode fazer:

(1234567.89).toLocaleString('en')              // for numeric input
parseFloat("1234567.89").toLocaleString('en')  // for string input

A função implementada abaixo também funciona, mas simplesmente não é necessária.

(Achei que talvez tivesse sorte e descobrisse que era necessário em 2010, mas não. De acordo com esta referência mais confiável , toLocaleString faz parte do padrão desde ECMAScript 3ª Edição [1999], o que acredito ser o mesmo. teria sido suportado desde o IE 5.5.)


Resposta Original

De acordo com esta referência, não existe uma função incorporada para adicionar vírgulas a um número. Mas essa página inclui um exemplo de como codificá-lo você mesmo:

function addCommas(nStr) {
    nStr += '';
    var x = nStr.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

Editar: para fazer o contrário (converter string com vírgulas em número), você poderia fazer algo assim:

parseFloat("1,234,567.89".replace(/,/g,''))
Tim Goodman
fonte
Realmente, Realmente Aprecio isso // Mas como posso converter essa string (com vírgulas) em um número?
LostLord de
esta função quebra para números maiores que 100.000
DevZer0
1
@ DevZer0 não, não faz
Tallboy
funciona com javascript puro + regex único substituir stackoverflow.com/a/44324879/681830
Val
4
usar (1234567).toLocaleString().replace(/,/g," ",)para espaços entre milhares
Fanky
122

Se se trata de localizar separadores de milhares, delimitadores e separadores decimais, vá com o seguinte:

// --> numObj.toLocaleString( [locales [, options] ] )
parseInt( number ).toLocaleString();

Existem várias opções que você pode usar (e até mesmo locais com substitutos):

number = 123456.7089;

result  = parseInt( number ).toLocaleString() + "<br>";
result += number.toLocaleString( 'de-DE' ) + "<br>";
result += number.toLocaleString( 'ar-EG' ) + "<br>";
result += number.toLocaleString( 'ja-JP', { 
  style           : 'currency',
  currency        : 'JPY',
  currencyDisplay : 'symbol',
  useGrouping     : true
} ) + "<br>";
result += number.toLocaleString( [ 'jav', 'en' ], { 
  localeMatcher            : 'lookup',
  style                    : 'decimal',
  minimumIntegerDigits     : 2,
  minimumFractionDigits    : 2,
  maximumFractionDigits    : 3,
  minimumSignificantDigits : 2,
  maximumSignificantDigits : 3
} ) + "<br>";

var el = document.getElementById( 'result' );
el.innerHTML = result;
<div id="result"></div>

Detalhes na página de informações do MDN .

Edit: Comentador @I like Serena adiciona o seguinte:

Para suportar navegadores com uma localidade diferente do inglês, onde ainda queremos a formatação em inglês, use value.toLocaleString('en'). Também funciona para ponto flutuante.

Kaiser
fonte
Isso não cobre números flutuantes .. você pode alterar parseInt para parseFloat, mas se yourInt = "100,12" (vírgula como separador decimal), isso falhará. Isso pode ser corrigido com um replace (",", ".") .. mas falhará novamente com "1.000,12". Então ... Você DEVE reinventar a roda às vezes. stackoverflow.com/a/2901298/1028304
neiker
Não funciona bem. Usa vírgula enquanto em nosso espaço local é comum para separador de milhares.
Josef Sábl
1
Isso seria mais apropriado:Number(yourNumberOrString).toLocaleString()
Jonathan
2
Para suportar navegadores com uma localidade diferente do inglês, onde ainda queremos a formatação em inglês, use value.toLocaleString('en'). Também funciona para ponto flutuante.
Klaas van Aarsen
1
@ Serhiog.Lazin O que exatamente não funciona no Safari (e em qual sistema operacional e em qual versão)?
Kaiser
34

Atualizado usando o suporte de look-behind de acordo com as alterações ECMAScript2018.
Para compatibilidade com versões anteriores, role mais para baixo para ver a solução original.

Uma expressão regular pode ser usada - notavelmente útil para lidar com grandes números armazenados como strings.

const format = num => 
    String(num).replace(/(?<!\..*)(\d)(?=(?:\d{3})+(?:\.|$))/g, '$1,')

;[
    format(100),                           // "100"
    format(1000),                          // "1,000"
    format(1e10),                          // "10,000,000,000"  
    format(1000.001001),                   // "1,000.001001"
    format('100000000000000.001001001001') // "100,000,000,000,000.001001001001
]
    .forEach(n => console.log(n))

»Explicação detalhada do regex (regex101.com) diagrama de fluxo


Esta resposta original pode não ser exigida, mas pode ser usada para compatibilidade com versões anteriores.

Tentando lidar com isso com uma única expressão regular (sem retorno de chamada), minha habilidade atual me falha por falta de um look-behind negativo em Javascript ... nunca menos aqui está outra alternativa concisa que funciona na maioria dos casos gerais - levando em conta qualquer ponto decimal ignorando correspondências em que o índice da correspondência aparece após o índice de um período.

const format = num => {
    const n = String(num),
          p = n.indexOf('.')
    return n.replace(
        /\d(?=(?:\d{3})+(?:\.|$))/g,
        (m, i) => p < 0 || i < p ? `${m},` : m
    )
}

;[
    format(100),                           // "100"
    format(1000),                          // "1,000"
    format(1e10),                          // "10,000,000,000"  
    format(1000.001001),                   // "1,000.001001"
    format('100000000000000.001001001001') // "100,000,000,000,000.001001001001
]
    .forEach(n => console.log(n))

»Explicação detalhada do regex (regex101.com)

diagrama de fluxo

Emissário
fonte
Este diagrama de sintaxe foi criado em regex101.com?
Gerold Broser,
o que acontece com números com decimais?
Emiliano
Estou recebendo "Expressão regular inválida: nome do especificador de grupo inválido". No React Native 0,59 fazendo isso, mas isso realmente não deve afetar o RegEx.
Joshua Pinter
@JoshuaPinter Será o uso de look-behind que, no momento da escrita, ainda não é suportado em todas as plataformas. Suponho que você esteja se referindo especificamente ao iOS - já que o Safari também falha para mim. Pode ser melhor ficar com a versão compatível por enquanto. Eu estava apenas tentando preparar minha resposta para o futuro. caniuse.com/#search=lookbehind
Emissário
1
@Emissary Obrigado pela dica. Sim, está no React Native 0.59 / Android, que usa uma versão relativamente mais antiga do JavaScriptCore (JSC). Vou tentar novamente depois de atualizar para React Native 0.60+, que inclui uma atualização para o JSC.
Joshua Pinter
10

Há um bom plugin de número jQuery: https://github.com/teamdf/jquery-number

Ele permite que você altere qualquer número no formato que desejar, com opções para dígitos decimais e caracteres separadores para decimal e mil:

$.number(12345.4556, 2);          // -> 12,345.46
$.number(12345.4556, 3, ',', ' ') // -> 12 345,456

Você pode usá-lo dentro dos campos de entrada diretamente, o que é melhor, usando as mesmas opções acima:

$("input").number(true, 2);

Ou você pode aplicar a todo um conjunto de elementos DOM usando o seletor:

$('span.number').number(true, 2);
qdev
fonte
melhor solução imho
Michal
Acho que não, adicionando um novo requisito de arquivo com quase 800 linhas, é como matar uma formiga com um granade
Emiliano
6

Eu uso isso:

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

fonte: link

Abhishek Goel
fonte
'123452343267.0505'.replace(/\B(?=(\d{3})+(?!\d))/g, ","); "123,452,343,267.0,505"- observe a última vírgula após o ponto decimal.
hippietrail,
5
// thousand separates a digit-only string using commas
// by element:  onkeyup = "ThousandSeparate(this)"
// by ID:       onkeyup = "ThousandSeparate('txt1','lbl1')"
function ThousandSeparate()
{
    if (arguments.length == 1)
    {
        var V = arguments[0].value;
        V = V.replace(/,/g,'');
        var R = new RegExp('(-?[0-9]+)([0-9]{3})'); 
        while(R.test(V))
        {
            V = V.replace(R, '$1,$2');
        }
        arguments[0].value = V;
    }
    else  if ( arguments.length == 2)
    {
        var V = document.getElementById(arguments[0]).value;
        var R = new RegExp('(-?[0-9]+)([0-9]{3})'); 
        while(R.test(V))
        {
            V = V.replace(R, '$1,$2');
        }
        document.getElementById(arguments[1]).innerHTML = V;
    }
    else return false;
}   
h.foroutan
fonte
3

Você pode usar javascript. abaixo estão o código, será apenas acceptnumérico e umdot

aqui está o javascript

<script >

            function FormatCurrency(ctrl) {
                //Check if arrow keys are pressed - we want to allow navigation around textbox using arrow keys
                if (event.keyCode == 37 || event.keyCode == 38 || event.keyCode == 39 || event.keyCode == 40) {
                    return;
                }

                var val = ctrl.value;

                val = val.replace(/,/g, "")
                ctrl.value = "";
                val += '';
                x = val.split('.');
                x1 = x[0];
                x2 = x.length > 1 ? '.' + x[1] : '';

                var rgx = /(\d+)(\d{3})/;

                while (rgx.test(x1)) {
                    x1 = x1.replace(rgx, '$1' + ',' + '$2');
                }

                ctrl.value = x1 + x2;
            }

            function CheckNumeric() {
                return event.keyCode >= 48 && event.keyCode <= 57 || event.keyCode == 46;
            }

  </script>

HTML

<input type="text" onkeypress="return CheckNumeric()" onkeyup="FormatCurrency(this)" />

DEMO JSFIDDLE

Awtszs
fonte
2
number = 123456.7089;
result = parseInt( number ).toLocaleString() + "<br>";
result = number.toLocaleString( 'pt-BR' ) + "<br>";

var el = document.getElementById( 'result' );
el.innerHTML = result;
<div id="result"></div>
Ricardo
fonte
6
Você também pode adicionar alguma descrição para que op e outras pessoas possam entender como esse código realmente resolve o problema. Obrigado
Punit Gajjar
tente com um nomber entre 1000 e 9999
Emiliano
1

PHP.js tem uma função para fazer isso chamada number_format . Se você estiver familiarizado com PHP, ele funciona exatamente da mesma maneira .

istvanp
fonte
O primeiro link segue para a implementação JS da versão do PHP. É útil.
o_nix
1

Tudo que você precisa fazer é realmente isto :

123000.9123.toLocaleString()
//result will be "123,000.912"
Ezeewei
fonte
Infelizmente, depende da sua plataforma. Alguns possuem um toLocaleString()que não adiciona vírgulas ou não possuem outros recursos no padrão. É fácil verificar a toLocaleStringpresença, mas não verificar sua conformidade.
hippietrail,
tente com um número entre 1000 e 9999
Emiliano
0

Combinação de soluções para reagir

  let converter = Intl.NumberFormat();
  let salary =  monthlySalary.replace(/,/g,'')
  console.log(converter.format(salary))

  this.setState({
    monthlySalary: converter.format(salary)
  })
}

handleOnChangeMonthlySalary(1000)```
Chinedu Ofor
fonte
0

Você pode usar ngx-format-field. É uma diretiva para formatar o valor de entrada que aparecerá na visualização. Não irá manipular o valor de entrada que será salvo no backend. Veja o link aqui !

Exemplo:

component.html:

<input type="text" formControlName="currency" [appFormatFields]="CURRENCY"
(change)="onChangeCurrency()">

component.ts

onChangeCurrency() {
this.currency.patchValue(this.currency.value);
}

Para ver a demonstração: aqui !

moumita kundu
fonte
0

Você pode usar a seguinte função:

function format(number, decimals = 2, decimalSeparator = '.', thousandsSeparator = ',') {
  const roundedNumber = number.toFixed(decimals);
  let integerPart = '',
    fractionalPart = '';
  if (decimals == 0) {
    integerPart = roundedNumber;
    decimalSeparator = '';
  } else {
    let numberParts = roundedNumber.split('.');
    integerPart = numberParts[0];
    fractionalPart = numberParts[1];
  }
  integerPart = integerPart.replace(/(\d)(?=(\d{3})+(?!\d))/g, `$1${thousandsSeparator}`);
  return `${integerPart}${decimalSeparator}${fractionalPart}`;
}

// Use Example

let min = 1556454.0001;
let max = 15556982.9999;

console.time('number format');
for (let i = 0; i < 15; i++) {
  let randomNumber = Math.random() * (max - min) + min;
  let formated = format(randomNumber, 4, ',', '.'); // formated number

  console.log('number: ', randomNumber, '; formated: ', formated);
}
console.timeEnd('number format');

jin_maxtor
fonte
Não torne isso tão confuso. apenas use toLocaleString (). Mais informações em developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Sajad Saderi
@sajadsaderi Eu também uso o amigo toLocaleString (), mas esta função não me dá muita flexibilidade, então eu não tenho que lidar com abreviações regionais e outra pessoa poderia usá-la, pois a definição desta função é idêntica a number_format () função do php.
jin_maxtor
-1

Não gostei de nenhuma das respostas aqui, então criei uma função que funcionou para mim. Só quero compartilhar, caso alguém mais considere útil.

function getFormattedCurrency(num) {
    num = num.toFixed(2)
    var cents = (num - Math.floor(num)).toFixed(2);
    return Math.floor(num).toLocaleString() + '.' + cents.split('.')[1];
}
Spencer Sullivan
fonte