2,299.00
,我想将其解析为数字。我尝试使用parseFloat
,结果得到了2。我猜逗号是问题所在,但是应该如何正确地解决这个问题?只是移除逗号吗?```javascript parseFloat("2,299.00".replace(",", "")); ```
var x = parseFloat("2,299.00")
console.log(x);
2,299.00
,我想将其解析为数字。我尝试使用parseFloat
,结果得到了2。我猜逗号是问题所在,但是应该如何正确地解决这个问题?只是移除逗号吗?var x = parseFloat("2,299.00")
console.log(x);
是的,去掉逗号:
let output = parseFloat("2,299.00".replace(/,/g, ''));
console.log(output);
删除逗号可能存在潜在危险,因为正如其他评论中提到的那样,许多地区使用逗号表示不同含义(例如小数点)。
我不知道您的字符串是从哪里得来的,但在世界上一些地方 "2,299.00"
= 2.299
Intl
对象本可以是解决此问题的好方法,但不知何故,它们只发布了一个 Intl.NumberFormat.format()
API而没有 parse
对应项 :(
以任何国际化数字字符方式将带有这些字符的字符串解析为机器可识别数字的唯一方法是使用利用 CLDR 数据覆盖所有可能格式化数字字符串的库。http://cldr.unicode.org/
到目前为止,我发现以下两个最好的 JS 选项:
"2,299.00" == 2.299
都是不成立的。任何明智的人都会看这个数字并假定它是 2299
格式化到小数点后两位,在一种使用逗号分组和句点/小数点表示小数的格式中。除非你告诉我有一个地方他们使用句点分组小数,并在 1 2/3 组后停止?我认为那是胡说八道。无论如何,你可以使用由 Intl.NumberFormat
公开的格式化规则来构建一个解析器:请参见 是否有任何 JavaScript 标准 API 可以根据区域设置解析为数字? 的答案。 - Heretic Monkey在现代浏览器中,你可以使用内置的Intl.NumberFormat来检测浏览器数字格式,并将输入归一化以匹配。
function parseNumber(value, locales = navigator.languages) {
const example = Intl.NumberFormat(locales).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 }`);
}
显然还有一些优化和缓存的空间,但这在所有语言中都可以可靠地工作。
navigator.languages
传递给构造函数比传递 navigator.language
更好,不是吗?我在想这个问题,因为在书籍《现代 JavaScript 快速入门》第180页中建议使用前者。虽然不确定两者之间的区别是什么。 - Kohei Nozakien-US
,parseNumber("12,00")
将返回 1200
。如何改进代码以在字符串不正确时返回空字符串? - davidtingsu1e3
)。-
)以外的字符(如果需要支持一元正号+
,则还可保留一个+
)。
如果你可以假设小数点为十进制分隔符(但实际上在世界许多地方并非如此),那么代码可能如下所示:function convertToFloat(str) {
let body = str;
let sign = "";
const signMatch = /^\s*(-|\+)/.exec(str);
// Or if you don't want to support unary +:
// const signMatch = /^\s*(-)/.exec(str);
if (signMatch) {
body = str.substring(signMatch.index + 1);
sign = signMatch[1];
}
const updatedBody = str.replace(/[^\d\.]/g, "");
const num = parseFloat(sign + updatedBody);
return num;
}
实时示例(我添加了一个小数部分以显示其工作方式):
function convertToFloat(str) {
let body = str;
let sign = "";
const signMatch = /^\s*(-|\+)/.exec(str);
// Or if you don't want to support unary +:
// const signMatch = /^\s*(-)/.exec(str);
if (signMatch) {
body = str.substring(signMatch.index + 1);
sign = signMatch[1];
}
const updatedBody = str.replace(/[^\d\.]/g, "");
const num = parseFloat(sign + updatedBody);
return num;
}
console.log(convertToFloat("2,299.23"));
.
的地区(有很多这样的地方),您可以检测小数点并将检测到的小数点用于正则表达式中。以下是查找小数点的示例函数:function findDecimalSeparator() {
const num = 1.2;
if (typeof Intl === "object" && Intl && Intl.NumberFormat) {
// I'm surprised it's this much of a pain and am hoping I'm missing
// something in the API
const formatter = new Intl.NumberFormat();
const parts = formatter.formatToParts(num);
const decimal = parts.find(({ type }) => type === "decimal").value;
return decimal;
}
// Doesn't support `Intl.NumberFormat`, fall back to dodgy means
const str = num.toLocaleString();
const parts = /1(\D+)2/.exec(str);
return parts[1];
}
convertToFloat
看起来像这样:const decimal = findDecimalSeparator();
function convertToFloat(str) {
let body = str;
let sign = "";
const signMatch = /^\s*(-|\+)/.exec(str);
// Or if you don't want to support unary +:
// const signMatch = /^\s*(-)/.exec(str);
if (signMatch) {
body = str.substring(signMatch.index + 1);
sign = signMatch[1];
}
const rex = new RegExp(`${escapeRegex(decimal)}|-|\\+|\\D`, "g");
const updatedBody = body.replace(
rex,
(match) => match === decimal ? "." : ""
);
const num = parseFloat(sign + updatedBody);
return num;
}
实例演示:
const decimal = findDecimalSeparator();
function findDecimalSeparator() {
const num = 1.2;
if (typeof Intl === "object" && Intl && Intl.NumberFormat) {
// I'm surprised it's this much of a pain and am hoping I'm missing
// something in the API
const formatter = new Intl.NumberFormat();
const parts = formatter.formatToParts(num);
const decimal = parts.find(({ type }) => type === "decimal").value;
return decimal;
}
// Doesn't support `Intl.NumberFormat`, fall back to dodgy means
const str = num.toLocaleString();
const parts = /1(\D+)2/.exec(str);
return parts[1];
}
function escapeRegex(string) {
return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, "\\$&");
}
function convertToFloat(str) {
let body = str;
let sign = "";
const signMatch = /^\s*(-|\+)/.exec(str);
// Or if you don't want to support unary +:
// const signMatch = /^\s*(-)/.exec(str);
if (signMatch) {
body = str.substring(signMatch.index + 1);
sign = signMatch[1];
}
const rex = new RegExp(`${escapeRegex(decimal)}|-|\\+|\\D`, "g");
const updatedBody = body.replace(
rex,
(match) => match === decimal ? "." : ""
);
const num = parseFloat(sign + updatedBody);
return num;
}
function gid(id) {
const element = document.getElementById(id);
if (!element) {
throw new Error(`No element found for ID ${JSON.stringify(id)}`);
}
return element;
}
function onClick(id, handler) {
gid(id).addEventListener("click", handler);
}
onClick("convert", () => {
const str = gid("num").value;
const num = convertToFloat(str);
console.log(`${JSON.stringify(str)} => ${num}`);
});
<div>Enter a number using your locale's grouping and decimal separators, optionally prefaced with a minus sign (<code>-</code>) or plus sign (<code>+</code>):</div>
<input type="text" id="num" value="-123">
<input type="button" id="convert" value="Convert">
str = str.replace(/(\d+),(?=\d{3}(\D|$))/g, "$1");
这是我会用的,但我对正则表达式一窍不通,这是我在一些其他 SO 线程上找到的。 - Jon Taylor-
,它会保留它。OP 没有提到异构格式,只是使用 ,
作为分组分隔符。 - T.J. Crowderfunction 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。
3,00 €
也被替换为3.00。只是需要注意的是,3,001
格式化为3001
。为了避免这种情况,输入应始终带有小数符号。例如,3,001.00€
3,001.00
可以正确转换。另外,请更新jsfiddle。那里的0,124
仍然被转换为124。 - Arnis Juragastrg.indexOf(decimal) !== 0
。这将捕获.123和,123的情况,并将它们与0.123和0,123的情况视为相同。 - sunnymtnvar 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, "."));
Number("2,299.00".split(',').join('')); // 2299
split函数使用“,”作为分隔符将字符串拆分为数组,并返回一个数组。
join函数将从split函数返回的数组元素合并起来。
Number()函数将合并后的字符串转换为数字。
或者尝试这种更短的方法:
const myNum = +('2,299.00'.replace(",",""));
const myNum = +('2,022,233,988.55'.replace(/,/g,""));
// -> myNum = 2022233988.55
以下是与我类似的案例所使用的数组(用于类似的用例):
获取该数组的总和,可以按照以下方法进行操作:
const numbers = ["11", "7", "15/25", "18/5", "12", "16/25"]
parseFloat
我可能会丢失小数点,为了得到精确的总和,我必须先将正斜杠替换为点,然后将字符串转换为实际数字。const currectNumbers = numbers.map(num => +(num.replace("/",".")))
// or the longer approach:
const currectNumbers = numbers
.map(num => num.replace("/","."))
.map(num => parseFloat(num));
currectNumbers = [ 11, 7, 15.25, 18.5, 12, 16.25]
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(...)。
如果数字是百万级别的,所有这些答案都会失败。
使用replace方法,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(''));
parseFloat()
,则会依赖于区域设置。解决区域问题的一种方法是将小数点分隔的数字输出为(part1 + part2/100).toFixed(2)
。 - Jon.replaceAll(",", "")
。 - Sebastian Simon