Javascript 如何将带有逗号千位分隔符的字符串解析为数字?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11665884/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 06:42:23  来源:igfitidea点击:

How can I parse a string with a comma thousand separator to a number?

javascriptnumber-formatting

提问by user1540714

I have 2,299.00as a string and I am trying to parse it to a number. I tried using parseFloat, which results in 2. I guess the comma is the problem, but how would I solve this issue the right way? Just remove the comma?

我有2,299.00一个字符串,我试图将它解析为一个数字。我尝试使用parseFloat,结果为 2。我想逗号是问题所在,但我将如何以正确的方式解决此问题?去掉逗号就可以了?

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

回答by Sam

Yes remove the commas:

是删除逗号:

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

回答by David Meister

Removing commas is potentially dangerous because, as others have mentioned in the comments, many locales use a comma to mean something different (like a decimal place).

删除逗号有潜在危险,因为正如其他人在评论中提到的那样,许多语言环境使用逗号来表示不同的东西(如小数位)。

I don't know where you got your string from, but in some places in the world "2,299.00"= 2.299

我不知道你从哪里得到你的字符串,但在世界上的某些地方"2,299.00"=2.299

The Intlobject could have been a nice way to tackle this problem, but somehow they managed to ship the spec with only a Intl.NumberFormat.format()API and no parsecounterpart :(

Intl对象可能是解决此问题的好方法,但不知何故,他们设法仅使用Intl.NumberFormat.format()API 而没有parse对应物来发布规范:(

The only way to parse a string with cultural numeric characters in it to a machine recognisable number in any i18n sane way is to use a library that leverages CLDR data to cover off all possible ways of formatting number strings http://cldr.unicode.org/

以任何 i18n 理智的方式将包含文化数字字符的字符串解析为机器可识别的数字的唯一方法是使用利用 CLDR 数据的库来覆盖所有可能的格式化数字字符串的方法http://cldr.unicode。组织/

The two best JS options I've come across for this so far:

到目前为止,我遇到的两个最好的 JS 选项:

回答by Paul Alexander

On modern browsers you can use the built in Intl.NumberFormatto detect the browser's number formatting and normalize the input to match.

在现代浏览器上,您可以使用内置的Intl.NumberFormat来检测浏览器的数字格式并将输入规范化以匹配。

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 }`);
}

Their's obviously room for some optimization and caching but this works reliably in all languages.

它们显然有一些优化和缓存的空间,但这在所有语言中都可以可靠地工作。

回答by T.J. Crowder

Remove anything that isn't a digit, decimal point, or minus sign (-):

删除不是数字、小数点或减号 ( -) 的任何内容:

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);

Updated fiddle

更新的小提琴

Note that it won't work for numbers in scientific notation. If you want it to, change the replaceline to add e, E, and +to the list of acceptable characters:

请注意,它不适用于科学记数法中的数字。如果你想让它,改变replace行添加eE+到可接受的字符列表:

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

回答by Gerfried

Usually you should consider to use input fields which don't allow free text input for numeric values. But there might be cases, when you need to guess the input format. For example 1.234,56 in Germany means 1,234.56 in US. See https://salesforce.stackexchange.com/a/21404for a list of countries which use comma as decimal.

通常您应该考虑使用不允许对数值进行自由文本输入的输入字段。但在某些情况下,您可能需要猜测输入格式。例如,德国的 1.234,56 表示美国的 1,234.56。有关使用逗号作为小数的国家/地区列表,请参阅https://salesforce.stackexchange.com/a/21404

I use the following function to do a best guess and strip off all non-numeric characters:

我使用以下函数进行最佳猜测并去除所有非数字字符:

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);
}   

Try it here: https://plnkr.co/edit/9p5Y6H?p=preview

在这里试试:https: //plnkr.co/edit/9p5Y6H?p=preview

Examples:

例子:

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

The function has one weak point: It is not possible to guess the format if you have 1,123 or 1.123 - because depending on the locale format both might be a comma or a thousands-separator. In this special case the function will treat separator as a thousands-separator and return 1123.

该函数有一个弱点:如果您有 1,123 或 1.123,则无法猜测格式 - 因为根据区域设置格式,两者都可能是逗号或千位分隔符。在这种特殊情况下,该函数会将分隔符视为千位分隔符并返回 1123。

回答by Fábio

It's baffling that they included a toLocaleStringbut not a parsemethod. At least toLocaleStringwithout arguments is well supported in IE6+.

令人费解的是,他们包含了一个toLocaleString而不是parse方法。至少没有参数的toLocaleString在 IE6+ 中得到了很好的支持。

For a i18nsolution, I came up with this:

对于i18n解决方案,我想出了这个:

First detect the user's locale decimal separator:

首先检测用户的语言环境十进制分隔符:

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

Then normalize the number if there's more than one decimal separator in the String:

如果字符串中有多个小数分隔符,则对数字进行标准化:

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

Finally, remove anything that is not a number or a decimal separator:

最后,删除任何不是数字或小数点分隔符的内容:

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

回答by Adam Jagosz

This is a simplistic unobtrusive wrapper around the parseFloatfunction.

这是一个围绕parseFloat函数的简单不显眼的包装器。

function parseLocaleNumber(str) {
  // Detect the user's locale decimal separator:
  var decimalSeparator = (1.1).toLocaleString().substring(1, 2);
  // Detect the user's locale thousand separator:
  var thousandSeparator = (1000).toLocaleString().substring(1, 2);
  // In case there are locales that don't use a thousand separator
  if (thousandSeparator.match(/\d/))
    thousandSeparator = '';

  str = str
    .replace(new RegExp(thousandSeparator, 'g'), '')
    .replace(new RegExp(decimalSeparator), '.')

  return parseFloat(str);
}

回答by Fernando Limeira

If you want to avoid the problem that David Meister posted and you are sure about the number of decimal places, you can replace all dots and commas and divide by 100, ex.:

如果你想避免 David Meister 贴出的问题并且你确定小数位数,你可以替换所有的点和逗号并除以 100,例如:

var value = "2,299.00";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/100;

or if you have 3 decimals

或者如果你有 3 位小数

var value = "2,299.001";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/1000;

It's up to you if you want to use parseInt, parseFloat or Number. Also If you want to keep the number of decimal places you can use the function .toFixed(...).

如果您想使用 parseInt、parseFloat 或 Number,这取决于您。此外,如果您想保留小数位数,您可以使用函数 .toFixed(...)。

回答by Eldar Gerfanov

This converts a number in whatever locale to normal number. Works for decimals points too:

这会将任何语言环境中的数字转换为正常数字。也适用于小数点:

function numberFromLocaleString(stringValue, locale){
    var parts = Number(1111.11).toLocaleString(locale).replace(/\d+/g,'').split('');
    if (stringValue === null)
        return null;
    if (parts.length==1) {
        parts.unshift('');
    }   
    return Number(String(stringValue).replace(new RegExp(parts[0].replace(/\s/g,' '),'g'), '').replace(parts[1],"."));
}
//Use default browser locale
numberFromLocaleString("1,223,333.567") //1223333.567

//Use specific locale
numberFromLocaleString("1?223?333,567", "ru") //1223333.567

回答by Case

All of these answers fail if you have a number in the millions.

如果你有数百万的数字,所有这些答案都失败了。

3,456,789 would simply return 3456 with the replace method.

3,456,789 将简单地使用替换方法返回 3456。

The most correct answer for simply removing the commas would have to be.

简单地删除逗号的最正确答案必须是。

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

Or simply written.

或者干脆写出来。

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