Como posso analisar uma string com um separador de vírgula mil em um número?

Eu tenho 2,299.00 como uma string e estou tentando analisá-lo para um número. Eu tentei usar parseFloat , o que resulta em 2. Eu acho que a vírgula é o problema, mas como eu iria resolver este problema da maneira correta? Apenas remova a vírgula?

Sim, remova as vírgulas:

 parseFloat(yournumber.replace(/,/g, '')); 

Remover vírgulas é potencialmente perigoso porque, como outros mencionaram nos comentários, muitas localidades usam uma vírgula para significar algo diferente (como uma casa decimal).

Eu não sei de onde você tirou sua corda, mas em alguns lugares do mundo "2,299.00" = 2.299

O object Intl poderia ter sido uma boa maneira de resolver esse problema, mas de alguma forma eles conseguiram enviar a especificação com apenas uma API Intl.NumberFormat.format() e nenhuma contrapartida de parse 🙁

A única maneira de analisar uma cadeia com caracteres numéricos culturais em um número reconhecível da máquina em qualquer modo i18n sane é usar uma biblioteca que aproveite dados CLDR para cobrir todas as formas possíveis de formatação de sequências numéricas http: //cldr.unicode. org /

As duas melhores opções de JS que encontrei até agora:

Remova tudo o que não seja um dígito, ponto decimal ou sinal de menos ( - ):

 var str = "2,299.00"; str = str.replace(/[^\d\.\-]/g, ""); // You might also include + if you want them to be able to type it var num = parseFloat(str); 

Violino atualizado

Note que não funcionará para números em notação científica. Se você quiser, altere a linha de replace para adicionar e , E e + à lista de caracteres aceitáveis:

 str = str.replace(/[^\d\.\-eE+]/g, ""); 

Em navegadores modernos, você pode usar o Intl.NumberFormat incorporado para detectar a formatação do número do navegador e normalizar a input para corresponder.

 function parseNumber(value, locale = navigator.language) { const example = Intl.NumberFormat(locale).format('1.1'); const cleanPattern = new RegExp(`[^-+0-9${ example.charAt( 1 ) }]`, 'g'); const cleaned = value.replace(cleanPattern, ''); const normalized = cleaned.replace(example.charAt(1), '.'); return parseFloat(normalized); } const corpus = { '1.123': { expected: 1.123, locale: 'en-US' }, '1,123': { expected: 1123, locale: 'en-US' }, '2.123': { expected: 2123, locale: 'fr-FR' }, '2,123': { expected: 2.123, locale: 'fr-FR' }, } for (const candidate in corpus) { const { locale, expected } = corpus[candidate]; const parsed = parseNumber(candidate, locale); console.log(`${ candidate } in ${ corpus[ candidate ].locale } == ${ expected }? ${ parsed === expected }`); } 

Normalmente você deve considerar usar campos de input que não permitem input de texto livre para valores numéricos. Mas pode haver casos em que você precisa adivinhar o formato de input. Por exemplo, 1.234,56 na Alemanha significa 1.234,56 nos EUA. Consulte https://salesforce.stackexchange.com/a/21404 para obter uma lista de países que usam vírgula como decimal.

Eu uso a seguinte function para fazer um melhor palpite e retirar todos os caracteres não numéricos:

 function parseNumber(strg) { var strg = strg || ""; var decimal = '.'; strg = strg.replace(/[^0-9$.,]/g, ''); if(strg.indexOf(',') > strg.indexOf('.')) decimal = ','; if((strg.match(new RegExp("\\" + decimal,"g")) || []).length > 1) decimal=""; if (decimal != "" && (strg.length - strg.indexOf(decimal) - 1 == 3) && strg.indexOf("0" + decimal)!==0) decimal = ""; strg = strg.replace(new RegExp("[^0-9$" + decimal + "]","g"), ""); strg = strg.replace(',', '.'); return parseFloat(strg); } 

Experimente aqui: https://plnkr.co/edit/9p5Y6H?p=preview

Exemplos:

 1.234,56 € => 1234.56 1,234.56USD => 1234.56 1,234,567€ => 1234567 1.234.567 => 1234567 1,234.567 => 1234.567 1.234 => 1234 // might be wrong - best guess 1,234 => 1234 // might be wrong - best guess 1.2345 => 1.2345 0,123 => 0.123 

A function tem um ponto fraco: Não é possível adivinhar o formato se você tiver 1,123 ou 1.123 – porque dependendo do formato de localidade, ambos podem ser uma vírgula ou um separador de milhares. Neste caso especial, a function tratará o separador como um separador de milhares e retornará 1123.

Todas essas respostas falham se você tiver um número na casa dos milhões.

3.456.789 simplesmente retornaria 3456 com o método replace.

A resposta mais correta para simplesmente remover as vírgulas teria que ser.

 var number = '3,456,789.12'; number.split(',').join(''); /* number now equips 3456789.12 */ parseFloat(number); 

Ou simplesmente escrito.

 number = parseFloat(number.split(',').join('')); 

Se você quer uma resposta l10n, faça assim. Exemplo usa moeda, mas você não precisa disso. A biblioteca Intl precisará ser polyfilled se você tiver que suportar navegadores mais antigos.

 var value = "2,299.00"; var currencyId = "USD"; var nf = new Intl.NumberFormat(undefined, {style:'currency', currency: currencyId, minimumFractionDigits: 2}); value = nf.format(value.replace(/,/g, "")); 

Substitua a vírgula por uma string vazia:

 var x = parseFloat("2,299.00".replace(",","")) alert(x); 

Se você tiver um pequeno conjunto de localidades para suportar, provavelmente ficará melhor apenas codificando algumas regras simples:

 function parseNumber(str, locale) { let radix = ','; if (locale.match(/(en|th)([-_].+)?/)) { radix = '.'; } return Number(str .replace(new RegExp('[^\\d\\' + radix + ']', 'g'), '') .replace(radix, '.')); } 

É desconcertante que eles incluam um toLocaleString, mas não um método de análise . Pelo menos, toLocaleString sem argumentos é bem suportado no IE6 +.

Para uma solução i18n , eu inventei isso:

Primeiro, detecte o separador decimal de localidade do usuário:

 var decimalSeparator = 1.1; decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2); 

Em seguida, normalize o número, se houver mais de um separador decimal na string:

 var pattern = "([" + decimalSeparator + "])(?=.*\\1)";separator var formatted = valor.replace(new RegExp(pattern, "g"), ""); 

Por fim, remova tudo o que não seja um número ou um separador decimal:

 formatted = formatted.replace(new RegExp("[^0-9" + decimalSeparator + "]", "g"), ''); return Number(formatted.replace(decimalSeparator, "."));