如何检查一个字符串是否是有效的数字?

1911

我希望有与旧的VB6 IsNumeric()函数在同一概念空间中的东西?


5
请参考我之前提出的相关问题此链接 - Michael Haren
55
如果您查看这个问题,请尽量跳过所有正则表达式的答案。那不是解决问题的正确方式。 - Joel Coehoorn
18
除非有人想要做这件事:检查给定字符串是否具有有效数字流的格式。那么为什么这样做是错的呢? - SasQ
41
选定的答案是不正确的!!!请查看其评论,但基本上它在例如isNaN("")isNaN(" ")isNaN(false)等情况下失败了。它返回false,这意味着它们是数字。 - Andrew
11
所选答案是不正确的,正则表达式也不能解决这个问题。那么正确的方法是什么? - vir us
显示剩余3条评论
53个回答

5

引用:

isNaN(num) // 如果变量不包含有效数字,则返回true

如果您需要检查前导/尾随空格,例如需要某个数量的数字,并且您需要获取'1111'而不是' 111'或'111 '(例如PIN输入),则这并不完全正确。

最好使用:

var num = /^\d+$/.test(num)

'-1''0.1''1e10'都返回false。此外,大于正无穷小于负无穷的值返回true,但它们应该返回false。 - Rudey

5

当防止空字符串和null

// Base cases that are handled properly
Number.isNaN(Number('1')); // => false
Number.isNaN(Number('-1')); // => false
Number.isNaN(Number('1.1')); // => false
Number.isNaN(Number('-1.1')); // => false
Number.isNaN(Number('asdf')); // => true
Number.isNaN(Number(undefined)); // => true

// Special notation cases that are handled properly
Number.isNaN(Number('1e1')); // => false
Number.isNaN(Number('1e-1')); // => false
Number.isNaN(Number('-1e1')); // => false
Number.isNaN(Number('-1e-1')); // => false
Number.isNaN(Number('0b1')); // => false
Number.isNaN(Number('0o1')); // => false
Number.isNaN(Number('0xa')); // => false

// Edge cases that will FAIL if not guarded against
Number.isNaN(Number('')); // => false
Number.isNaN(Number(' ')); // => false
Number.isNaN(Number(null)); // => false

// Edge cases that are debatable
Number.isNaN(Number('-0b1')); // => true
Number.isNaN(Number('-0o1')); // => true
Number.isNaN(Number('-0xa')); // => true
Number.isNaN(Number('Infinity')); // => false 
Number.isNaN(Number('INFINITY')); // => true  
Number.isNaN(Number('-Infinity')); // => false 
Number.isNaN(Number('-INFINITY')); // => true  

当不考虑空字符串和 null 值时, 使用 parseInt:
// Base cases that are handled properly
Number.isNaN(parseInt('1')); // => false
Number.isNaN(parseInt('-1')); // => false
Number.isNaN(parseInt('1.1')); // => false
Number.isNaN(parseInt('-1.1')); // => false
Number.isNaN(parseInt('asdf')); // => true
Number.isNaN(parseInt(undefined)); // => true
Number.isNaN(parseInt('')); // => true
Number.isNaN(parseInt(' ')); // => true
Number.isNaN(parseInt(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseInt('1e1')); // => false
Number.isNaN(parseInt('1e-1')); // => false
Number.isNaN(parseInt('-1e1')); // => false
Number.isNaN(parseInt('-1e-1')); // => false
Number.isNaN(parseInt('0b1')); // => false
Number.isNaN(parseInt('0o1')); // => false
Number.isNaN(parseInt('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseInt('-0b1')); // => false
Number.isNaN(parseInt('-0o1')); // => false
Number.isNaN(parseInt('-0xa')); // => false
Number.isNaN(parseInt('Infinity')); // => true 
Number.isNaN(parseInt('INFINITY')); // => true  
Number.isNaN(parseInt('-Infinity')); // => true 
Number.isNaN(parseInt('-INFINITY')); // => true 

使用parseFloat:
// Base cases that are handled properly
Number.isNaN(parseFloat('1')); // => false
Number.isNaN(parseFloat('-1')); // => false
Number.isNaN(parseFloat('1.1')); // => false
Number.isNaN(parseFloat('-1.1')); // => false
Number.isNaN(parseFloat('asdf')); // => true
Number.isNaN(parseFloat(undefined)); // => true
Number.isNaN(parseFloat('')); // => true
Number.isNaN(parseFloat(' ')); // => true
Number.isNaN(parseFloat(null)); // => true

// Special notation cases that are handled properly
Number.isNaN(parseFloat('1e1')); // => false
Number.isNaN(parseFloat('1e-1')); // => false
Number.isNaN(parseFloat('-1e1')); // => false
Number.isNaN(parseFloat('-1e-1')); // => false
Number.isNaN(parseFloat('0b1')); // => false
Number.isNaN(parseFloat('0o1')); // => false
Number.isNaN(parseFloat('0xa')); // => false

// Edge cases that are debatable
Number.isNaN(parseFloat('-0b1')); // => false
Number.isNaN(parseFloat('-0o1')); // => false
Number.isNaN(parseFloat('-0xa')); // => false
Number.isNaN(parseFloat('Infinity')); // => false 
Number.isNaN(parseFloat('INFINITY')); // => true  
Number.isNaN(parseFloat('-Infinity')); // => false 
Number.isNaN(parseFloat('-INFINITY')); // => true

注:

  • 只有字符串、空值和未初始化的值被认为是符合原问题的。如果考虑到数组和对象等其他情况,则存在额外的边缘情况。
  • 二进制、八进制、十六进制和指数表示法中的字符不区分大小写(例如:'0xFF'、'0XFF'、'0xfF'等在上述测试用例中将产生相同的结果)。
  • Infinity(区分大小写)不同,从NumberMath对象传递给上述任何方法的常量(以字符串格式)将被确定为不是数字。
  • 请参阅此处,了解如何将参数转换为Number以及为什么存在null和空字符串的边缘情况的说明。

请参见 https://dev59.com/KlYN5IYBdhLWcg3w7MC5 - Philip
失败包括 ""nullundefined - gman
@gman 感谢指出边缘情况。我更新了答案以解决您提到的那些情况,包括 Infinity"Infinity"。看起来 undefined 已经被正确处理,但我明确地添加了它以使其更清晰。 - Abtin Gramian

4

这是基于之前的答案和评论构建的。它涵盖了所有边缘情况,并可选择处理科学计数法:

const NUMBER_REG_EXP = /^-?\d+(?:\.\d+)?$/;
const SCIENTIFIC_NOTATION_REG_EXP = /^-?\d+(?:\.\d+)?(?:[eE]\d+)?$/;

const isNumeric = (n, allowScientificNotation = false) => (
    (typeof n === 'number' && !Number.isNaN(n)) || 
    (typeof n === 'string' && (allowScientificNotation ?
        SCIENTIFIC_NOTATION_REG_EXP : NUMBER_REG_EXP).test(n))
);

3

我最近撰写了一篇关于确保变量是有效数字的方法的文章: https://github.com/jehugaleahsa/artifacts/blob/master/2018/typescript_num_hack.md 该文章解释了如何确保浮点数或整数,如果这很重要 (+x vs ~~x)。

该文章假设变量起始为 stringnumber ,并且已经存在 trim 或填充。很容易扩展它来处理其他类型。下面是核心内容:

// Check for a valid float
if (x == null
    || ("" + x).trim() === ""
    || isNaN(+x)) {
    return false;  // not a float
}

// Check for a valid integer
if (x == null
    || ("" + x).trim() === ""
    || ~~x !== +x) {
    return false;  // not an integer
}

3
如果有人看到了这里,我花了一些时间尝试着修补moment.js (https://github.com/moment/moment)。以下是我得出的一些结论:
function isNumeric(val) {
    var _val = +val;
    return (val !== val + 1) //infinity check
        && (_val === +val) //Cute coercion check
        && (typeof val !== 'object') //Array/object check
}

处理以下情况:

True! :

真的!:
isNumeric("1"))
isNumeric(1e10))
isNumeric(1E10))
isNumeric(+"6e4"))
isNumeric("1.2222"))
isNumeric("-1.2222"))
isNumeric("-1.222200000000000000"))
isNumeric("1.222200000000000000"))
isNumeric(1))
isNumeric(0))
isNumeric(-0))
isNumeric(1010010293029))
isNumeric(1.100393830000))
isNumeric(Math.LN2))
isNumeric(Math.PI))
isNumeric(5e10))

错误!:

isNumeric(NaN))
isNumeric(Infinity))
isNumeric(-Infinity))
isNumeric())
isNumeric(undefined))
isNumeric('[1,2,3]'))
isNumeric({a:1,b:2}))
isNumeric(null))
isNumeric([1]))
isNumeric(new Date()))

具有讽刺意味的是,我最苦恼的正是这个:

isNumeric(new Number(1)) => false

欢迎提出任何建议。:]

2
isNumeric(' ')isNumeric('')怎么处理? - Alex Cory
为解决上述问题和我自己遇到的问题,我会添加 && (val.replace(/\s/g,'') !== '') //非空 && (val.slice(-1) !== '.') //无数字小数点 - frankenapps

3
function isNumberCandidate(s) {
  const str = (''+ s).trim();
  if (str.length === 0) return false;
  return !isNaN(+str);
}

console.log(isNumberCandidate('1'));       // true
console.log(isNumberCandidate('a'));       // false
console.log(isNumberCandidate('000'));     // true
console.log(isNumberCandidate('1a'));      // false 
console.log(isNumberCandidate('1e'));      // false
console.log(isNumberCandidate('1e-1'));    // true
console.log(isNumberCandidate('123.3'));   // true
console.log(isNumberCandidate(''));        // false
console.log(isNumberCandidate(' '));       // false
console.log(isNumberCandidate(1));         // true
console.log(isNumberCandidate(0));         // true
console.log(isNumberCandidate(NaN));       // false
console.log(isNumberCandidate(undefined)); // false
console.log(isNumberCandidate(null));      // false
console.log(isNumberCandidate(-1));        // true
console.log(isNumberCandidate('-1'));      // true
console.log(isNumberCandidate('-1.2'));    // true
console.log(isNumberCandidate(0.0000001)); // true
console.log(isNumberCandidate('0.0000001')); // true
console.log(isNumberCandidate(Infinity));    // true
console.log(isNumberCandidate(-Infinity));    // true

console.log(isNumberCandidate('Infinity'));  // true

if (isNumberCandidate(s)) {
  // use +s as a number
  +s ...
}

3

因此,这将取决于您希望它处理的测试用例。

function isNumeric(number) {
  return !isNaN(parseFloat(number)) && !isNaN(+number);
}

我需要的是javascript中常规数字类型。以下是示例:0, 1 , -1, 1.1 , -1.1 , 1E1 , -1E1 , 1e1 , -1e1, 0.1e10, -0.1.e10 , 0xAF1 , 0o172, Math.PI, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY
它们也可以表示为字符串:'0', '1', '-1', '1.1', '-1.1', '1E1', '-1E1', '1e1', '-1e1', '0.1e10', '-0.1.e10', '0xAF1', '0o172'
我不想将以下内容标记为数字:'', ' ', [], {}, null, undefined, NaN
截至今天,所有其他答案似乎都未通过这些测试用例。

1
请注意,如果这对您有影响,isNumeric('007')返回true - epan

2

好的,我正在使用我制作的这个...

目前为止它一直在工作:

function checkNumber(value) {
    return value % 1 == 0;
}

如果您发现任何问题,请告诉我。

21
这会导致空字符串、空数组、false和null的结果错误。 - Ori
2
应该使用三个等于号才对吧? - toasted_flakes
1
在我的应用程序中,我们只允许使用a-z、A-Z和0-9字符。我发现上述方法有效,除非字符串以0xnn开头,否则它会将其作为数字返回,而实际上不应该这样做。我已在下面的评论中发布了代码,以保持格式的完整性。 - rwheadon
7
你可以这样写:'return value % 1 === 0',意思是判断“value”是否为整数。 - Brian Schermerhorn
只需执行 return !isNaN(parseInt(value, 10)); - DarkNeuron

2
你还可以使用一个简单的 parseInt 函数... 加上 if 条件语句,例如:
if (parseInt(i)){
    (i in dic) ? dic[i] += 1 : dic[i] = 1
}

2

这似乎可以解决看似无穷无尽的边缘情况:

function isNumber(x, noStr) {
    /*

        - Returns true if x is either a finite number type or a string containing only a number
        - If empty string supplied, fall back to explicit false
        - Pass true for noStr to return false when typeof x is "string", off by default

        isNumber(); // false
        isNumber([]); // false
        isNumber([1]); // false
        isNumber([1,2]); // false
        isNumber(''); // false
        isNumber(null); // false
        isNumber({}); // false
        isNumber(true); // false
        isNumber('true'); // false
        isNumber('false'); // false
        isNumber('123asdf'); // false
        isNumber('123.asdf'); // false
        isNumber(undefined); // false
        isNumber(Number.POSITIVE_INFINITY); // false
        isNumber(Number.NEGATIVE_INFINITY); // false
        isNumber('Infinity'); // false
        isNumber('-Infinity'); // false
        isNumber(Number.NaN); // false
        isNumber(new Date('December 17, 1995 03:24:00')); // false
        isNumber(0); // true
        isNumber('0'); // true
        isNumber(123); // true
        isNumber(123.456); // true
        isNumber(-123.456); // true
        isNumber(-.123456); // true
        isNumber('123'); // true
        isNumber('123.456'); // true
        isNumber('.123'); // true
        isNumber(.123); // true
        isNumber(Number.MAX_SAFE_INTEGER); // true
        isNumber(Number.MAX_VALUE); // true
        isNumber(Number.MIN_VALUE); // true
        isNumber(new Number(123)); // true
    */

    return (
        (typeof x === 'number' || x instanceof Number || (!noStr && x && typeof x === 'string' && !isNaN(x))) &&
        isFinite(x)
    ) || false;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接