63

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

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

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

使用 jQuery 和 jQuery UI。Number(string)返回NaNparseFloat()在第一个空格或逗号处停止。

4

12 回答 12

57

先做一个替换:

parseFloat(str.replace(',','.').replace(' ',''))
于 2011-09-15T13:45:14.240 回答
26

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

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}$为与您期望的小数点后的值适当匹配的特定用例。

于 2015-03-30T13:10:14.207 回答
21

完美的解决方案

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

检查这个以获取参考

于 2013-02-13T05:33:08.827 回答
9

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

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

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

于 2011-09-15T13:47:32.033 回答
7

这是最好的解决方案

http://numeraljs.com/

numeral().unformat('0.02'); = 0.02
于 2015-07-28T17:31:35.257 回答
6

关于什么:

parseFloat(str.replace(' ', '').replace('.', '').replace(',', '.'));
于 2016-12-08T16:43:35.337 回答
5

所有其他解决方案都需要您提前知道格式。我需要在每种情况下检测(!)格式,这就是我最终得到的。

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

欢迎提出建议。

于 2017-04-19T10:19:00.810 回答
4

这是一个自给自足的 JS 函数,它解决了大多数欧洲/美国语言环境的这个(和其他)问题(主要是在美国/德国/瑞典数字分块和格式化之间......就像在 OP 中一样)。我认为这是对 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
    }
}
于 2019-10-30T18:31:40.193 回答
4

这是我没有任何依赖关系的解决方案:

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

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

该代码假定:

  • 只有逗号和句点用作小数分隔符。(我不确定是否存在使用其他语言环境的语言环境。)
  • 字符串的小数部分不使用任何分隔符。
于 2020-05-08T12:57:30.220 回答
1

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

  • 只有千位分隔符: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>

于 2021-01-20T15:34:09.483 回答
0

试试这个...

var withComma = "23,3";
var withFloat = "23.3";

var compareValue = function(str){
  var fixed = parseFloat(str.replace(',','.'))
  if(fixed > 0){
      console.log(true)
    }else{
      console.log(false);
  }
}
compareValue(withComma);
compareValue(withFloat);
于 2020-05-07T19:42:23.840 回答
-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

于 2016-10-06T12:27:59.903 回答