如何使用逗号千位分隔符将字符串解析为数字?

use*_*714 77 javascript number-formatting

我有2,299.00一个字符串,我试图解析它的数字.我尝试使用parseFloat,结果是2.我猜逗号是问题,但我怎么能以正确的方式解决这个问题呢?只需删除逗号?

var x = parseFloat("2,299.00")
alert(x);
Run Code Online (Sandbox Code Playgroud)

小智 90

是删除逗号:

parseFloat(yournumber.replace(/,/g, ''));
Run Code Online (Sandbox Code Playgroud)

  • 我建议我们使用以下命令捕获所有逗号:`.replace(/,/ g,'')`这个正则表达式使用全局`g`来替换所有. (35认同)
  • 我不知道为什么这个答案得到了如此多的赞成并被选为正确的,它有两个严重的问题.1.它无法处理带有多个逗号的数字,例如`parseFloat("2,000,000.00".replace(',',''))`返回`2000`和2.它在世界上许多地区失败,其中`,`是一个小数位,例如`parseFloat("2.000.000,00".replace(',',''))`返回`2` - 请参阅下面的答案,了解世界上无处不在的东西. (20认同)
  • 是的,但现在小数位丢失了.例如,2300.00以2300结果. (5认同)
  • 如果可以的话,我会将@gdibble评为1,000,000次. (5认同)
  • 在法语区域设置中,逗号是小数点分隔符...因此,对于浏览器设置了法语区域设置的很可能情况,这会失败 (5认同)

Dav*_*ter 73

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

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

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

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

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

  • 完全同意Intl应该有一个解析对应物.很明显人们会需要这个. (3认同)
  • 不能相信没有人赞成这个答案,这是这个页面上唯一的实际答案! (2认同)
  • 实际上,世界上没有任何地方会“2,299.00”== 2.299。任何理智的人都会看到这个数字,并假设它是“2299”,格式为两位小数,格式使用逗号进行分组,使用句点/句号表示小数。除非你告诉我有一个地方使用句点对小数进行分组并在 1 2/3 组后停止?我打电话给BS。在任何情况下,您都可以使用“Intl.NumberFormat”公开的格式规则来构建解析器:请参阅[Is there any JavaScript standard API to parse to number due to locale?](https://stackoverflow.com)的答案/q/55364947/215552) (2认同)

Pau*_*der 28

在现代浏览器中,您可以使用内置的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 }`);
}
Run Code Online (Sandbox Code Playgroud)

它们显然有一些优化和缓存的空间,但这在所有语言中都可靠地运行.


T.J*_*der 24

删除任何非数字,小数点或减号(-)的内容:

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);
Run Code Online (Sandbox Code Playgroud)

更新了小提琴

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

str = str.replace(/[^\d\.\-eE+]/g, "");
Run Code Online (Sandbox Code Playgroud)

  • 这对于科学记数法中的负数或数字不起作用. (3认同)

Ger*_*ied 13

通常,您应该考虑使用不允许自由文本输入数字值的输入字段.但是,当您需要猜测输入格式时,可能会出现这种情况.例如,德国的1.234,56在美国意味着1,234.56.有关使用逗号作为十进制的国家/地区列表,请参阅https://salesforce.stackexchange.com/a/21404.

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

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);
}   
Run Code Online (Sandbox Code Playgroud)

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

例子:

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
Run Code Online (Sandbox Code Playgroud)

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


Fáb*_*bio 5

令人困惑的是它们包括一个toLocaleString而不是一个parse方法。IE6 + 至少支持不带参数的toLocaleString

对于i18n解决方案,我提出了以下方案:

首先检测用户的语言环境小数点分隔符:

var decimalSeparator = 1.1;
decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2);
Run Code Online (Sandbox Code Playgroud)

如果字符串中有多个小数点分隔符,则将数字标准化:

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

最后,删除所有不是数字或小数点的分隔符:

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