将带有点或逗号的字符串作为小数分隔符转换为JavaScript中的数字

时间:2011-09-15 13:42:09

标签: javascript jquery string-parsing data-conversion

输入元素包含数字a,其中逗号或点用作小数分隔符,空格可用于对数千个进行分组,如下所示:

  

'1,2'
  '110 000,23'
  '100 1.23'

如何使用JavaScript在浏览器中将它们转换为浮点数?

使用jQuery和jQuery UI。 Number(string)在第一个空格或逗号上停止 NaN parseFloat()停止。

11 个答案:

答案 0 :(得分:41)

首先替换:

parseFloat(str.replace(',','.').replace(' ',''))

答案 1 :(得分:17)

完美的解决方案

accounting.js是一个用于数字,金钱和货币格式的小型JavaScript库。

Check this for ref

答案 2 :(得分:15)

我意识到我已经迟到了,但我想要一个解决方案,正确处理数字分组以及货币的不同小数分隔符。由于这些都没有完全涵盖我的用例,我编写了自己的解决方案,这可能对其他人有用:

function parsePotentiallyGroupedFloat(stringValue) {
    stringValue = stringValue.trim();
    var result = stringValue.replace(/[^0-9]/g, '');
    if (/[,\.]\d{2}$/.test(stringValue)) {
        result = result.replace(/(\d{2})$/, '.$1');
    }
    return parseFloat(result);
}

这应该删除任何非数字,然后检查是否有小数点(或逗号)后跟两位数字,并在需要时插入小数点。

值得注意的是,我专门针对货币而将其定位,因此它假设没有小数位或正好两位。很难确定遇到的第一个可能的小数点是小数点还是数字分组字符(例如,1.542可能是1542),除非你知道具体的细节当前的语言环境,但它应该很容易通过将\d{2}$更改为与小数点后的预期相匹配的内容来根据您的特定用例进行定制。

答案 3 :(得分:9)

您可以用空字符串替换所有空格,所有逗号都用点替换,然后解析它。

var str = "110 000,23";
var num = parseFloat(str.replace(/\s/g, "").replace(",", "."));
console.log(num);

我在第一个中使用正则表达式来匹配所有空格,而不仅仅是第一个空格。

答案 4 :(得分:7)

这是最好的解决方案

http://numeraljs.com/

AppClientDetailsUserDetailsService

答案 5 :(得分:6)

怎么样:

parseFloat(str.replace(' ', '').replace('.', '').replace(',', '.'));

答案 6 :(得分:4)

所有其他解决方案都要求您事先了解格式。我需要在每种情况下检测(!)格式,这就是我最终的结果。

function detectFloat(source) {
    let float = accounting.unformat(source);
    let posComma = source.indexOf(',');
    if (posComma > -1) {
        let posDot = source.indexOf('.');
        if (posDot > -1 && posComma > posDot) {
            let germanFloat = accounting.unformat(source, ',');
            if (Math.abs(germanFloat) > Math.abs(float)) {
                float = germanFloat;
            }
        } else {
            // source = source.replace(/,/g, '.');
            float = accounting.unformat(source, ',');
        }
    }
    return float;
}

对此进行了测试,结果如下:

        const cases = {
            "0": 0,
            "10.12": 10.12,
            "222.20": 222.20,
            "-222.20": -222.20,
            "+222,20": 222.20,
            "-222,20": -222.20,
            "-2.222,20": -2222.20,
            "-11.111,20": -11111.20,
        };

建议欢迎。

答案 7 :(得分:2)

这是一个自给自足的JS函数,可以解决大多数欧洲/美国语言环境(主要是在OP / US / German / Swedish数字分块和格式设置之间...)中的此问题(以及其他问题)。我认为这是对Slawa解决方案的改进(并受其启发),并且没有依赖性。

function realParseFloat(s)
{
    s = s.replace(/[^\d,.-]/g, ''); // strip everything except numbers, dots, commas and negative sign
    if (navigator.language.substring(0, 2) !== "de" && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(s)) // if not in German locale and matches #,###.######
    {
        s = s.replace(/,/g, ''); // strip out commas
        return parseFloat(s); // convert to number
    }
    else if (/^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(s)) // either in German locale or not match #,###.###### and now matches #.###,########
    {
        s = s.replace(/\./g, ''); // strip out dots
        s = s.replace(/,/g, '.'); // replace comma with dot
        return parseFloat(s);
    }
    else // try #,###.###### anyway
    {
        s = s.replace(/,/g, ''); // strip out commas
        return parseFloat(s); // convert to number
    }
}

答案 8 :(得分:1)

这是我的解决方案,没有任何依赖性:

return value
  .replace(/[^\d\-.,]/g, "")   // Basic sanitization. Allows '-' for negative numbers.
  .replace(",", ".")           // Change all commas to periods.
  .replace(/\.(?=.*\.)/g, ""); // Remove all periods except the last one.

(我忽略了转换为数字的操作-如果您不关心JavaScript的浮点精度问题,那可能只是parseFloat调用。)

代码假定:

  • 仅逗号和句点用作小数点分隔符。 (我不确定是否存在使用其他语言环境的语言。)
  • 字符串的小数部分不使用任何分隔符。

答案 9 :(得分:0)

这个答案接受一些其他人不接受的边缘情况:

  • 只有千位分隔符:1.000.000 => 1000000
  • 指数:1.000e3 => 1000e3(100 万)

运行代码片段以查看所有测试套件。

const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINNING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g

export function formatNumber(number) {
  // Handle exponentials
  if ((number.match(/e/g) ?? []).length === 1) {
    const numberParts = number.split('e')
    return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
  }

  const sanitizedNumber = number
    .replace(REGEX_UNWANTED_CHARACTERS, '')
    .replace(REGEX_DASHES_EXEPT_BEGINING, '')

  // Handle only thousands separator
  if (
    ((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
    ((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
  ) {
    return sanitizedNumber.replace(/[.,]/g, '')
  }

  return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}

function formatNumberToNumber(number) {
  return Number(formatNumber(number))
}

const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g

function formatNumber(number) {
  if ((number.match(/e/g) ?? []).length === 1) {
    const numberParts = number.split('e')
    return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
  }

  const sanitizedNumber = number
    .replace(REGEX_UNWANTED_CHARACTERS, '')
    .replace(REGEX_DASHES_EXEPT_BEGINING, '')

  if (
    ((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
    ((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
  ) {
    return sanitizedNumber.replace(/[.,]/g, '')
  }

  return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}

const testCases = [
  '1',
  '1.',
  '1,',
  '1.5',
  '1,5',
  '1,000.5',
  '1.000,5',
  '1,000,000.5',
  '1.000.000,5',
  '1,000,000',
  '1.000.000',

  '-1',
  '-1.',
  '-1,',
  '-1.5',
  '-1,5',
  '-1,000.5',
  '-1.000,5',
  '-1,000,000.5',
  '-1.000.000,5',
  '-1,000,000',
  '-1.000.000',

  '1e3',
  '1e-3',
  '1e',
  '-1e',
  '1.000e3',
  '1,000e-3',
  '1.000,5e3',
  '1,000.5e-3',
  '1.000,5e1.000,5',
  '1,000.5e-1,000.5',

  '',
  'a',
  'a1',
  'a-1',
  '1a',
  '-1a',
  '1a1',
  '1a-1',
  '1-',
  '-',
  '1-1'
]

document.getElementById('tbody').innerHTML = testCases.reduce((total, input) => {
  return `${total}<tr><td>${input}</td><td>${formatNumber(input)}</td></tr>`
}, '')
<table>
  <thead><tr><th>Input</th><th>Output</th></tr></thead>
  <tbody id="tbody"></tbody>
</table>

答案 10 :(得分:-1)

从数字到货币字符串很容易通过Number.prototype.toLocaleString。然而,反过来似乎是一个普遍的问题。 JS标准中可能无法获得千位分隔符和小数点。

在此特定问题中,千位分隔符是空格" ",但在许多情况下,它可以是句点".",小数点可以是逗号","。例如1 000 000,001.000.000,00。然后这就是我如何将其转换为适当的浮点数。

var price = "1 000.000,99",
    value = +price.replace(/(\.|\s)|(\,)/g,(m,p1,p2) => p1 ? "" : ".");
console.log(value);

因此,替换者回调需要"1.000.000,00"并将其转换为"1000000.00"。之后,结果字符串前面的+将其强制转换为数字。

这个功能实际上非常方便。例如,如果您在回调函数中将p1 = ""部分替换为p1 = ",",则1.000.000,00的输入将导致1,000,000.00