在 JavaScript 中验证十进制数的最简洁,最有效的方法是什么?
奖励积分:
测试用例:
01. IsNumeric('-1') => true
02. IsNumeric('-1.5') => true
03. IsNumeric('0') => true
04. IsNumeric('0.42') => true
05. IsNumeric('.42') => true
06. IsNumeric('99,999') => false
07. IsNumeric('0x89f') => false
08. IsNumeric('#abcdef') => false
09. IsNumeric('1.2.3') => false
10. IsNumeric('') => false
11. IsNumeric('blah') => false
@ Joel 的答案非常接近,但在以下情况下会失败:
// Whitespace strings:
IsNumeric(' ') == true;
IsNumeric('\t\t') == true;
IsNumeric('\n\r') == true;
// Number literals:
IsNumeric(-1) == false;
IsNumeric(0) == false;
IsNumeric(1.1) == false;
IsNumeric(8e5) == false;
前段时间我不得不实现一个IsNumeric
函数,以确定变量是否包含数值, 无论其类型如何 ,它都可以是包含数值的String
(我还必须考虑指数表示法等), Number
对象,几乎任何东西都可以传递给那个函数,我不能做任何类型的假设,照顾类型强制(例如。 +true == 1;
但是true
不应该被认为是"numeric"
)。
我认为值得分享这套针对众多功能实现的+30 单元测试 ,并且还共享通过我所有测试的那个:
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
由于强制转换为数字, PS isNaN & isFinite具有令人困惑的行为。在 ES6 中, Number.isNaN和Number.isFinite将解决这些问题。使用它们时请记住这一点。
更新 : 这是 jQuery 现在如何做到的(2.2 稳定) :
isNumeric: function(obj) {
var realStringObj = obj && obj.toString();
return !jQuery.isArray(obj) && (realStringObj - parseFloat(realStringObj) + 1) >= 0;
}
更新 : Angular 4.3 :
export function isNumeric(value: any): boolean {
return !isNaN(value - parseFloat(value));
}
Arrrgh!不要听正则表达式的答案。 RegEx 对此非常苛刻,我不只是说性能。用你的正则表达式来制作微妙的,不可能发现错误是如此容易。
如果你不能使用isNaN()
,这应该会更好:
function IsNumeric(input)
{
return (input - 0) == input && (''+input).trim().length > 0;
}
以下是它的工作原理:
(input - 0)
表达式强制 JavaScript 对输入值进行类型强制; 必须首先将其解释为减法运算的数字。如果转换为数字失败,则表达式将导致NaN
。然后将此数值结果与您传入的原始值进行比较。由于左侧现在是数字,因此再次使用类型强制。既然来自双方的输入都是从相同的原始值强制转换为相同的类型,那么您会认为它们应该始终相同(始终为真)。但是,有一个特殊的规则,即NaN
永远不会等于NaN
,因此无法转换为数字的值(并且只有无法转换为数字的值)将导致错误。
检查长度是针对涉及空字符串的特殊情况。另请注意,它会降低到您的 0x89f 测试,但这是因为在许多环境中,这是一种定义数字文字的好方法。如果要捕获该特定方案,可以添加其他检查。更好的是,如果这是你不使用isNaN()
原因,那么只需在isNaN()
周围包装你自己的函数,它也可以进行额外的检查。
总之, 如果您想知道某个值是否可以转换为数字,请务必尝试将其转换为数字。
我回去做了一些研究, 为什么空格字符串没有预期的输出,我想我现在得到它:一个空字符串被强制为0
而不是NaN
。只需在长度检查之前修剪字符串就可以处理这种情况。
运行单元测试新代码,它只在无限和布尔文字上失败,唯一应该是问题的是你生成代码(真的,谁会输入文字并检查它是否是数字?你应该知道 ),这将是一些奇怪的代码生成。
但是,再一次, 使用它的唯一原因是,如果由于某种原因你必须避免使用 isNaN()。
这种方式似乎运作良好:
function IsNumeric(input){
var RE = /^-{0,1}\d*\.{0,1}\d+$/;
return (RE.test(input));
}
并测试它:
// alert(TestIsNumeric());
function TestIsNumeric(){
var results = ''
results += (IsNumeric('-1')?"Pass":"Fail") + ": IsNumeric('-1') => true\n";
results += (IsNumeric('-1.5')?"Pass":"Fail") + ": IsNumeric('-1.5') => true\n";
results += (IsNumeric('0')?"Pass":"Fail") + ": IsNumeric('0') => true\n";
results += (IsNumeric('0.42')?"Pass":"Fail") + ": IsNumeric('0.42') => true\n";
results += (IsNumeric('.42')?"Pass":"Fail") + ": IsNumeric('.42') => true\n";
results += (!IsNumeric('99,999')?"Pass":"Fail") + ": IsNumeric('99,999') => false\n";
results += (!IsNumeric('0x89f')?"Pass":"Fail") + ": IsNumeric('0x89f') => false\n";
results += (!IsNumeric('#abcdef')?"Pass":"Fail") + ": IsNumeric('#abcdef') => false\n";
results += (!IsNumeric('1.2.3')?"Pass":"Fail") + ": IsNumeric('1.2.3') => false\n";
results += (!IsNumeric('')?"Pass":"Fail") + ": IsNumeric('') => false\n";
results += (!IsNumeric('blah')?"Pass":"Fail") + ": IsNumeric('blah') => false\n";
return results;
}
我从http://www.codetoad.com/javascript/isnumeric.asp借用了这个正则表达式。说明:
/^ match beginning of string
-{0,1} optional negative sign
\d* optional digits
\.{0,1} optional decimal point
\d+ at least one digit
$/ match end of string