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

时间:2012-07-26 09:04:36

标签: javascript number-formatting

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

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

16 个答案:

答案 0 :(得分:72)

是删除逗号:

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

答案 1 :(得分:58)

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

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

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

使用文本数字字符将字符串解析为机器可识别数字的唯一方法是使用CLDR数据来覆盖格式化数字字符串http://cldr.unicode.org/的所有可能方式

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

答案 2 :(得分: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);

Updated fiddle

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

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

答案 3 :(得分:23)

在现代浏览器上,您可以使用内置的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 }`);
}

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

答案 4 :(得分:11)

通常您应该考虑使用不允许自由文本输入数字值的输入字段。但是,当您需要猜测输入格式时,可能会出现这种情况。例如,德国的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);
}   

在此处试试: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

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

答案 5 :(得分:3)

令人困惑的是,它们包括一个 toLocaleString ,但没有一个 parse 方法。在IE6 +中,至少至少支持 toLocaleString 不带参数。

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

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

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

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

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

最后,删除所有非数字或小数点分隔符的内容:

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

答案 6 :(得分:1)

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

3,456,789只会使用替换方法返回3456。

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

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

或者简单地写。

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

答案 7 :(得分:1)

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

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

答案 8 :(得分:1)

const parseLocaleNumber = strNum => {
    const decSep = (1.1).toLocaleString().substring(1, 2);
    const formatted = strNum
        .replace(new RegExp(`([${decSep}])(?=.*\\1)`, 'g'), '')
        .replace(new RegExp(`[^0-9${decSep}]`, 'g'), '');
    return Number(formatted.replace(decSep, '.'));
};

答案 9 :(得分:1)

使用此功能,您将能够以多种格式设置值的格式,例如1.234,561,234.56,甚至出现诸如1.234.561,234,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);
}
parseFloatFromString('1.234,56')
"1234.56"
parseFloatFromString('1,234.56')
"1234.56"
parseFloatFromString('1.234.56')
"1234.56"
parseFloatFromString('1,234,56')
"1234.56"

答案 10 :(得分:0)

用空字符串替换逗号:

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

答案 11 :(得分:0)

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

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

答案 12 :(得分:0)

如果你有一小部分语言环境可以支持你,那么通过硬编码几个简单的规则可能会更好:

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

答案 13 :(得分:0)

如果要避免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(...)。

答案 14 :(得分:0)

这是一个简单的parseFloat函数周围的包装器。

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

答案 15 :(得分:0)

Number("2,299.00".split(',').join(''));   // 2299

split函数使用“,”作为分隔符将字符串拆分为一个数组,并返回一个数组。
join函数连接从split函数返回的数组元素。
Number()函数将连接的字符串转换为数字。