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

Javascript 如何将带有逗号分隔符的字符串解析为数字?,javascript,number-formatting,Javascript,Number Formatting,我将2299.00作为一个字符串,并试图将其解析为一个数字。我尝试使用parseFloat,结果是2。我想逗号是个问题,但我该如何正确地解决这个问题呢?去掉逗号 var x=parseFloat(“2299.00”) 控制台日志(x)删除任何不是数字、小数点或减号(-)的内容: 请注意,它不适用于科学记数法中的数字。如果需要,请将replace行更改为将e、e和+添加到可接受字符列表中: str = str.replace(/[^\d\.\-eE+]/g, ""); function pa

我将
2299.00
作为一个字符串,并试图将其解析为一个数字。我尝试使用
parseFloat
,结果是2。我想逗号是个问题,但我该如何正确地解决这个问题呢?去掉逗号

var x=parseFloat(“2299.00”)

控制台日志(x)删除任何不是数字、小数点或减号(
-
)的内容:

请注意,它不适用于科学记数法中的数字。如果需要,请将
replace
行更改为将
e
e
+
添加到可接受字符列表中:

str = str.replace(/[^\d\.\-eE+]/g, "");
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);
}   

将逗号替换为空字符串:

var x=parseFloat(“2299.00”。替换(“,”,”)
警报(x)是删除逗号:

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

如果你想要一个l10n答案,就这样做。示例使用货币,但您不需要。如果您必须支持较旧的浏览器,则需要对Intl库进行多填充

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

如果你有数以百万计的数字,所有这些答案都会失败

3456789将简单地使用replace方法返回3456

简单删除逗号的最正确答案是

var number = '3,456,789.12';
number.split(',').join('');
/* number now equips 3456789.12 */
parseFloat(number);
或者干脆写下来

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

删除逗号有潜在的危险,因为正如其他人在评论中提到的那样,许多地区使用逗号表示不同的意思(如小数点)

我不知道你的字符串是从哪里来的,但是在世界上的一些地方
“2299.00”
=
2.299

Intl
对象本来是解决这个问题的好方法,但不知何故,他们设法只提供了一个
Intl.NumberFormat.format()
API和no
parse
对应项:(

以任何i18n合理的方式将包含文化数字字符的字符串解析为机器可识别的数字的唯一方法是使用一个库,该库利用CLDR数据覆盖所有可能的格式化数字字符串的方法

到目前为止,我在这方面遇到了两个最好的JS选项:


通常你应该考虑使用不允许输入数字文本的输入字段。但是当需要猜测输入格式时,可能会有一些情况。例如,德国中的1.23、56是指美国的1234.56。请参阅使用逗号为十进制的国家的列表。< /P> 我使用以下函数进行最佳猜测并去除所有非数字字符:

str = str.replace(/[^\d\.\-eE+]/g, "");
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);
}   
请在此处尝试:

示例:

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

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

在现代浏览器上,可以使用内置的来检测浏览器的数字格式设置和输入的规格化匹配

function parseNumber(值,locales=navigator.languages){
const example=Intl.NumberFormat(locales.format('1.1');
const cleanPattern=newregexp(`[^-+0-9${example.charAt(1)}]`g');
const cleaned=value.replace(cleanPattern.);
const normalized=cleaned.replace(例如.charAt(1),'.');
返回浮点(标准化);
}
常量语料库={
'1.123': {
预计:1.123,
地点:“en US”
},
'1,123': {
预计:1123,
地点:“en US”
},
'2.123': {
预计:2123,
区域设置:“fr”
},
'2,123': {
预计:2.123,
区域设置:“fr”
},
}
for(语料库中的const候选者){
常数{
场所
预期
}=语料库[候选人];
const parsed=parseNumber(候选语言,区域设置);
log(${corpus[candidate].locale}=${expected}?${parsed===expected}中的${candidate});

}
如果您有一小部分区域设置需要支持,那么只需硬编码两条简单规则可能会更好:

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

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

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

首先检测用户的区域设置十进制分隔符:

var decimalSeparator = 1.1;
decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2);
formatted = formatted.replace(new RegExp("[^0-9" + decimalSeparator + "]", "g"), '');
return Number(formatted.replace(decimalSeparator, "."));
然后,如果字符串中有多个十进制分隔符,则对数字进行规格化:

var pattern = "([" + decimalSeparator + "])(?=.*\\1)";separator
var formatted = valor.replace(new RegExp(pattern, "g"), "");
最后,删除任何不是数字或十进制分隔符的内容:

var decimalSeparator = 1.1;
decimalSeparator = decimalSeparator.toLocaleString().substring(1, 2);
formatted = formatted.replace(new RegExp("[^0-9" + decimalSeparator + "]", "g"), '');
return Number(formatted.replace(decimalSeparator, "."));

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

var value = "2,299.00";
var amount = parseFloat(value.replace(/"|\,|\./g, ''))/100;
或者如果你有3个小数

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

如果要使用parseInt、parseFloat或Number,则由您决定。此外,如果要保留小数位数,则可以使用函数.toFixed(…)。

此函数可将任何区域设置中的数字转换为正常数字。 也适用于小数点:

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],"."));
}

使用此功能,您将能够以多种格式格式化值,如
1.234,56
1234.56
,即使出现
1.234.56
1234,56

/**
 * @param {string} value: value to convert
 * @param {bool} coerce: force float return or NaN
 */
function parseFloatFromString(value, coerce) {
    value = String(value).trim();

    if ('' === value) {
        return value;
    }

    // check if the string can be converted to float as-is
    var parsed = parseFloat(value);
    if (String(parsed) === value) {
        return fixDecimals(parsed, 2);
    }

    // replace arabic numbers by latin
    value = value
    // arabic
    .replace(/[\u0660-\u0669]/g, function(d) {
        return d.charCodeAt(0) - 1632;
    })

    // persian
    .replace(/[\u06F0-\u06F9]/g, function(d) {
        return d.charCodeAt(0) - 1776;
    });

    // remove all non-digit characters
    var split = value.split(/[^\dE-]+/);

    if (1 === split.length) {
        // there's no decimal part
        return fixDecimals(parseFloat(value), 2);
    }

    for (var i = 0; i < split.length; i++) {
        if ('' === split[i]) {
            return coerce ? fixDecimals(parseFloat(0), 2) : NaN;
        }
    }

    // use the last part as decimal
    var decimal = split.pop();

    // reconstruct the number using dot as decimal separator
    return fixDecimals(parseFloat(split.join('') +  '.' + decimal), 2);
}

function fixDecimals(num, precision) {
    return (Math.floor(num * 100) / 100).toFixed(precision);
}
split函数使用“,”作为分隔符将字符串拆分为一个数组,并返回一个数组。
join函数连接从split函数返回的数组元素。

函数的作用是:将连接的字符串转换为数字。

这不适用于负数或科学记数法中的数字。
str=str.replace(/(\d+),(?=\d{3}(\d |$)/g,“$1”)这是我要用的,但我在正则表达式中完全没有用处,这是我不久前在另一个SO线程中发现的东西。@JonTaylor:这里的目标不是验证数字,只是让它为
parseFloat
——它将验证它。:-)据我所知,我的是这样做的。我用它将1234567等转换为1234567。正如我所说,虽然我在regex完全没用,所以我一辈子都不能告诉你它到底做了什么
Number("2,299.00".split(',').join(''));   // 2299