Xác thực số thập phân trong JavaScript - IsNumeric ()


2376

Cách sạch nhất, hiệu quả nhất để xác thực số thập phân trong JavaScript là gì?

Điểm thưởng cho:

  1. Trong trẻo. Giải pháp nên sạch sẽ và đơn giản.
  2. Đa nền tảng.

Các trường hợp thử nghiệm:

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

256
Chỉ cần một lưu ý 99.999 là một số hợp lệ ở Pháp, giống như 99.999 ở định dạng uk / us, vì vậy nếu bạn đang đọc trong một chuỗi từ nói mẫu đầu vào thì 99.999 có thể đúng.
Re0sless


79
Dấu phẩy thập phân là tiêu chuẩn ở toàn bộ Châu Âu và Nga (trừ Vương quốc Anh)
Calmarius

90
jQuery 1.7 đã giới thiệu jQuery.isNumericchức năng tiện ích: api.jquery.com/jQuery.isNumeric
Ates Goral

24
jQuery.isNumericsẽ thất bại trong trường hợp thử nghiệm thứ bảy của OP ( IsNumeric('0x89f') => *false*). Tôi không chắc chắn nếu tôi đồng ý với trường hợp thử nghiệm này, tuy nhiên.
Tim Lehner

Câu trả lời:


2898

Câu trả lời của @ Joel khá gần, nhưng nó sẽ thất bại trong các trường hợp sau:

// 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;

Cách đây một thời gian, tôi đã phải thực hiện một IsNumerichàm, để tìm hiểu xem một biến có chứa một giá trị số hay không , bất kể loại nào , nó có thể là một Stringgiá trị số (tôi phải xem xét cả ký hiệu số mũ, v.v.), một Numberđối tượng, hầu như bất cứ điều gì có thể được chuyển đến chức năng đó, tôi không thể đưa ra bất kỳ giả định loại nào, quan tâm đến việc ép buộc kiểu (ví dụ: +true == 1;nhưng truekhông nên được coi là "numeric").

Tôi nghĩ rằng đáng để chia sẻ bộ thử nghiệm đơn vị +30 này được thực hiện cho nhiều lần triển khai chức năng và cũng chia sẻ thử nghiệm vượt qua tất cả các thử nghiệm của tôi:

function isNumeric(n) {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

PS isNaN & isFinite có hành vi khó hiểu do buộc phải chuyển đổi thành số. Trong ES6, Number.isNaN & Number.isFinite sẽ khắc phục các sự cố này. Hãy ghi nhớ điều đó khi sử dụng chúng.


Cập nhật : Đây là cách jQuery thực hiện ngay bây giờ (ổn định 2.2) :

isNumeric: function(obj) {
    var realStringObj = obj && obj.toString();
    return !jQuery.isArray(obj) && (realStringObj - parseFloat(realStringObj) + 1) >= 0;
}

Cập nhật : Góc 4.3 :

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}

26
điều này không thành công với các địa phương khác nơi chúng tôi sử dụng dấu phẩy thập phân, nhưng thêm `n = n.replace (/, /,". "); ' trước khi trở về để sửa nó.
Zoltan Lengyel

5
@RobG, hành vi đó là cố ý, 2e308 > Number.MAX_VALUEkể từ đó 2e308 == Infinity. Nếu bạn muốn một hàm truecũng trả về giá trị vô cực dương và âm, hãy kiểm tra hàm số 2 trong bộ kiểm tra . Chúc mừng.
CMS

39
Nhân tiện, các bài kiểm tra đơn vị hiện đang được sử dụng bởi dự án jQuery
CMS

7
jQuery hiện cũng đang sử dụng triển khai này.
RichardTowers

4
Giải pháp ở đây là chỉ sử dụng JQuery. Họ thậm chí còn thực hiện tốt hơn việc này: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli

337

Cố lên! Đừng nghe những câu trả lời thường xuyên. RegEx là tuyệt vời cho điều này, và tôi không chỉ nói về hiệu suất. Thật dễ dàng để làm cho tinh tế, không thể phát hiện ra lỗi với biểu hiện thông thường của bạn.

Nếu bạn không thể sử dụng isNaN(), điều này sẽ hoạt động tốt hơn nhiều:

function IsNumeric(input)
{
    return (input - 0) == input && (''+input).trim().length > 0;
}

Đây là cách nó hoạt động:

Các (input - 0)biểu hiện buộc hoạt Javascript để làm kiểu ép buộc trên giá trị đầu vào của bạn; đầu tiên nó phải được hiểu là một số cho phép toán trừ. Nếu chuyển đổi thành một số không thành công, biểu thức sẽ dẫn đến NaN. Đây số kết quả là sau đó so sánh với giá trị ban đầu bạn thông qua năm. Kể từ phía bên tay trái là tại số, kiểu ép buộc được một lần nữa sử dụng. Bây giờ, đầu vào từ cả hai phía đã bị ép buộc cùng loại từ cùng một giá trị ban đầu, bạn sẽ nghĩ rằng chúng phải luôn giống nhau (luôn luôn đúng). Tuy nhiên, có một quy tắc đặc biệt nói rằng NaNkhông bao giờ bằng NaN, và do đó, một giá trị không thể được chuyển đổi thành một số (và chỉ các giá trị không thể chuyển đổi thành số) sẽ dẫn đến sai.

Việc kiểm tra độ dài dành cho trường hợp đặc biệt liên quan đến chuỗi rỗng. Cũng lưu ý rằng nó rơi vào bài kiểm tra 0x89f của bạn, nhưng đó là bởi vì trong nhiều môi trường, đó là một cách ổn để xác định một số theo nghĩa đen. Nếu bạn muốn nắm bắt kịch bản cụ thể đó, bạn có thể thêm một kiểm tra bổ sung. Thậm chí tốt hơn, nếu đó là lý do của bạn không sử dụng isNaN()thì chỉ cần bọc chức năng của riêng bạn xung quanh isNaN()cũng có thể thực hiện kiểm tra bổ sung.

Tóm lại, nếu bạn muốn biết liệu một giá trị có thể được chuyển đổi thành một số hay không, hãy thử chuyển đổi nó thành một số.


Tôi đã quay lại và thực hiện một số nghiên cứu về lý do tại sao một chuỗi khoảng trắng không có đầu ra mong đợi và tôi nghĩ rằng tôi đã nhận được ngay bây giờ: một chuỗi trống bị ép buộc 0thay vì NaN. Đơn giản chỉ cần cắt xén chuỗi trước khi kiểm tra độ dài sẽ xử lý trường hợp này.

Chạy thử nghiệm đơn vị đối với mã mới và nó chỉ thất bại ở các chữ vô cực và boolean, và lần duy nhất có vấn đề là nếu bạn đang tạo mã (thực sự, ai sẽ nhập bằng chữ và kiểm tra xem nó có phải là số không? Bạn nên biết ), và đó sẽ là một số mã lạ để tạo.

Nhưng, một lần nữa, lý do duy nhất từng sử dụng điều này là nếu vì lý do nào đó bạn phải tránh isNaN ().


28
Đây không thành công trên dây khoảng trắng, ví dụ như IsNumeric(' '), IsNumeric('\n\t'), vv tất cả trở lạitrue
Crescent Fresh

29
Nó cũng sẽ thất bại khi kiểm tra nghĩa Numberđen IsNumeric(5) == false;của bộ bài kiểm tra đơn vị tôi đã đăng, chức năng này là số 16trên bộ kiểm tra. stackoverflow.com/questions/18082/NH
CMS

20
Tôi không thể tin rằng không ai chỉ ra việc sử dụng biểu thức chính quy (thay thế) sau khi cảnh báo về việc không sử dụng biểu thức thông thường ... Được cấp, thay thế khoảng trắng đơn giản hơn so với phân tích số, nhưng nó vẫn chắc chắn là "icky".
Patrick M

1
@Oriol Đó là một vấn đề lớn ... không có bản sửa lỗi bảo mật nào được phát hành sau ngày đó, nên tránh xa XP là ưu tiên hàng đầu.
Joel Coehoorn

1
@Oriol XP hay không, nếu bạn đang sử dụng IE8 hoặc thấp hơn, bạn đang sử dụng phần mềm lỗi thời khủng khiếp. Cấp XP không thể chạy IE9 + nên sử dụng Chrome hoặc FF. Những người sống trong quá khứ sử dụng IE8 là nguyên nhân của sự tồn tại của nhiều nhà phát triển web. Nếu tôi có thể lấy lại thời gian tôi đã dành để đảm bảo mã hoàn toàn tốt cũng chạy trong IE8 ... Đối với tôi, việc lấy mã hoạt động trong FF và Chrome và vá nó để chạy trong IE8 là về việc thực thi một Windows 8 thực thi và đảm bảo nó chạy tương tự trong windows 3.1.
chiliNUT

70

Cách này có vẻ hoạt động tốt:

function IsNumeric(input){
    var RE = /^-{0,1}\d*\.{0,1}\d+$/;
    return (RE.test(input));
}

Trong một dòng:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);

Và để kiểm tra nó:

const IsNumeric = (num) => /^-{0,1}\d*\.{0,1}\d+$/.test(num);
    
    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;
    }

console.log(TestIsNumeric());
.as-console-wrapper { max-height: 100% !important; top: 0; }

Tôi đã mượn regex đó từ http://www.codetoad.com/javascript/isnumeric.asp . Giải trình:

/^ 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

1
// CSONG NÊN ĐƯỢC THÊM VÀO kết quả KIỂM TRA CỦA BẠN + = (! IsNumeric ('-')? "Đạt": "Fail") + ": IsNumeric ('-') => false \ n"; results + = (! IsNumeric ('01 ')? "Pass": "Fail") + ": IsNumeric ('01') => false \ n"; results + = (! IsNumeric ('- 01')? "Pass": "Fail") + ": IsNumeric ('- 01') => false \ n"; results + = (! IsNumeric ('000')? "Pass": "Fail") + ": IsNumeric ('000') => false \ n";
Dan

cái này làm gì? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
hãy gọi cho tôi

"{0,1}" có thể được thay thế bằng "?", vì vậy biểu thức chính của bạn sẽ trông như thế này: / ^ -? \ d * \.? \ d +$ /?
Đám mây

đẹp và đơn giản.
kẻ phá vỡ

53

Yahoo! UI sử dụng điều này:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}

25
Đó là kiểm tra nhiều hơn các loại biến trái ngược với nội dung của số. Nó cũng sẽ thất bại trên những con số được tạo ra với new Number(1).
alex

4
Như alex nói, điều này không thực sự trả lời câu hỏi được đặt ra vì điều này sẽ thất bại nếu o = "1001".
Trường hợp

50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Điều này làm việc cho số loại 0x23 là tốt.


29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Trở lại truethay vì false.
Oriol

49

Câu trả lời được chấp nhận đã thất bại bài kiểm tra số 7 của bạn và tôi đoán đó là vì bạn đã thay đổi quyết định. Vì vậy, đây là một câu trả lời cho câu trả lời được chấp nhận, mà tôi đã có vấn đề.

Trong một số dự án tôi cần xác thực một số dữ liệu và chắc chắn nhất có thể rằng đó là một giá trị số javascript có thể được sử dụng trong các phép toán.

jQuery và một số thư viện javascript khác đã bao gồm một hàm như vậy, thường được gọi isNumeric. Ngoài ra còn có một bài đăng trên stackoverflow đã được chấp nhận rộng rãi như là câu trả lời, cùng một thói quen chung mà các thư viện đã đề cập ở trên đang sử dụng.

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

Đầu tiên, mã ở trên sẽ trả về true nếu đối số là một mảng có độ dài 1 và phần tử đơn đó thuộc loại được coi là số theo logic trên. Theo tôi, nếu đó là một mảng thì nó không phải là số.

Để giảm bớt vấn đề này, tôi đã thêm một kiểm tra vào mảng giảm giá từ logic

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n);
}

Tất nhiên, bạn cũng có thể sử dụng Array.isArray, jquery $.isArrayhoặc nguyên mẫu Object.isArraythay vìObject.prototype.toString.call(n) !== '[object Array]'

Vấn đề thứ hai của tôi là các chuỗi số nguyên thập lục phân âm ("-0xA" -> -10) không được tính là số. Tuy nhiên, các chuỗi số nguyên thập lục phân dương ("0xA" -> 10) được coi là số. Tôi cần cả hai để là số hợp lệ.

Sau đó tôi đã sửa đổi logic để tính đến điều này.

function isNumber(n) {
  return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

Nếu bạn lo lắng về việc tạo regex mỗi khi hàm được gọi thì bạn có thể viết lại nó trong một bao đóng, đại loại như thế này

var isNumber = (function () {
  var rx = /^-/;

  return function (n) {
      return Object.prototype.toString.call(n) !== '[object Array]' &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(rx, ''));
  };
}());

Sau đó, tôi đã lấy CMS +30 trường hợp thử nghiệm và nhân bản thử nghiệm trên jsfiddle đã thêm các trường hợp thử nghiệm bổ sung và giải pháp được mô tả ở trên của tôi.

Nó có thể không thay thế câu trả lời được chấp nhận / sử dụng rộng rãi nhưng nếu đây là nhiều hơn những gì bạn đang mong đợi vì kết quả từ hàm isNumeric của bạn thì hy vọng điều này sẽ giúp ích.

EDIT: Như Bergi đã chỉ ra , có những đối tượng khả dĩ khác có thể được coi là số và sẽ tốt hơn trong danh sách trắng hơn danh sách đen. Với suy nghĩ này, tôi sẽ thêm vào các tiêu chí.

Tôi muốn hàm isNumeric của tôi chỉ xem xét Số hoặc Chuỗi

Với suy nghĩ này, nó sẽ tốt hơn để sử dụng

function isNumber(n) {
  return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
}

Kiểm tra các giải pháp

var testHelper = function() {

  var testSuite = function() {
    test("Integer Literals", function() {
      ok(isNumber("-10"), "Negative integer string");
      ok(isNumber("0"), "Zero string");
      ok(isNumber("5"), "Positive integer string");
      ok(isNumber(-16), "Negative integer number");
      ok(isNumber(0), "Zero integer number");
      ok(isNumber(32), "Positive integer number");
      ok(isNumber("040"), "Octal integer literal string");
      ok(isNumber(0144), "Octal integer literal");
      ok(isNumber("-040"), "Negative Octal integer literal string");
      ok(isNumber(-0144), "Negative Octal integer literal");
      ok(isNumber("0xFF"), "Hexadecimal integer literal string");
      ok(isNumber(0xFFF), "Hexadecimal integer literal");
      ok(isNumber("-0xFF"), "Negative Hexadecimal integer literal string");
      ok(isNumber(-0xFFF), "Negative Hexadecimal integer literal");
    });

    test("Foating-Point Literals", function() {
      ok(isNumber("-1.6"), "Negative floating point string");
      ok(isNumber("4.536"), "Positive floating point string");
      ok(isNumber(-2.6), "Negative floating point number");
      ok(isNumber(3.1415), "Positive floating point number");
      ok(isNumber(8e5), "Exponential notation");
      ok(isNumber("123e-2"), "Exponential notation string");
    });

    test("Non-Numeric values", function() {
      equals(isNumber(""), false, "Empty string");
      equals(isNumber("        "), false, "Whitespace characters string");
      equals(isNumber("\t\t"), false, "Tab characters string");
      equals(isNumber("abcdefghijklm1234567890"), false, "Alphanumeric character string");
      equals(isNumber("xabcdefx"), false, "Non-numeric character string");
      equals(isNumber(true), false, "Boolean true literal");
      equals(isNumber(false), false, "Boolean false literal");
      equals(isNumber("bcfed5.2"), false, "Number with preceding non-numeric characters");
      equals(isNumber("7.2acdgs"), false, "Number with trailling non-numeric characters");
      equals(isNumber(undefined), false, "Undefined value");
      equals(isNumber(null), false, "Null value");
      equals(isNumber(NaN), false, "NaN value");
      equals(isNumber(Infinity), false, "Infinity primitive");
      equals(isNumber(Number.POSITIVE_INFINITY), false, "Positive Infinity");
      equals(isNumber(Number.NEGATIVE_INFINITY), false, "Negative Infinity");
      equals(isNumber(new Date(2009, 1, 1)), false, "Date object");
      equals(isNumber(new Object()), false, "Empty object");
      equals(isNumber(function() {}), false, "Instance of a function");
      equals(isNumber([]), false, "Empty Array");
      equals(isNumber(["-10"]), false, "Array Negative integer string");
      equals(isNumber(["0"]), false, "Array Zero string");
      equals(isNumber(["5"]), false, "Array Positive integer string");
      equals(isNumber([-16]), false, "Array Negative integer number");
      equals(isNumber([0]), false, "Array Zero integer number");
      equals(isNumber([32]), false, "Array Positive integer number");
      equals(isNumber(["040"]), false, "Array Octal integer literal string");
      equals(isNumber([0144]), false, "Array Octal integer literal");
      equals(isNumber(["-040"]), false, "Array Negative Octal integer literal string");
      equals(isNumber([-0144]), false, "Array Negative Octal integer literal");
      equals(isNumber(["0xFF"]), false, "Array Hexadecimal integer literal string");
      equals(isNumber([0xFFF]), false, "Array Hexadecimal integer literal");
      equals(isNumber(["-0xFF"]), false, "Array Negative Hexadecimal integer literal string");
      equals(isNumber([-0xFFF]), false, "Array Negative Hexadecimal integer literal");
      equals(isNumber([1, 2]), false, "Array with more than 1 Positive interger number");
      equals(isNumber([-1, -2]), false, "Array with more than 1 Negative interger number");
    });
  }

  var functionsToTest = [

    function(n) {
      return !isNaN(parseFloat(n)) && isFinite(n);
    },

    function(n) {
      return !isNaN(n) && !isNaN(parseFloat(n));
    },

    function(n) {
      return !isNaN((n));
    },

    function(n) {
      return !isNaN(parseFloat(n));
    },

    function(n) {
      return typeof(n) != "boolean" && !isNaN(n);
    },

    function(n) {
      return parseFloat(n) === Number(n);
    },

    function(n) {
      return parseInt(n) === Number(n);
    },

    function(n) {
      return !isNaN(Number(String(n)));
    },

    function(n) {
      return !isNaN(+('' + n));
    },

    function(n) {
      return (+n) == n;
    },

    function(n) {
      return n && /^-?\d+(\.\d+)?$/.test(n + '');
    },

    function(n) {
      return isFinite(Number(String(n)));
    },

    function(n) {
      return isFinite(String(n));
    },

    function(n) {
      return !isNaN(n) && !isNaN(parseFloat(n)) && isFinite(n);
    },

    function(n) {
      return parseFloat(n) == n;
    },

    function(n) {
      return (n - 0) == n && n.length > 0;
    },

    function(n) {
      return typeof n === 'number' && isFinite(n);
    },

    function(n) {
      return !Array.isArray(n) && !isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
    }

  ];


  // Examines the functionsToTest array, extracts the return statement of each function
  // and fills the toTest select element.
  var fillToTestSelect = function() {
    for (var i = 0; i < functionsToTest.length; i++) {
      var f = functionsToTest[i].toString();
      var option = /[\s\S]*return ([\s\S]*);/.exec(f)[1];
      $("#toTest").append('<option value="' + i + '">' + (i + 1) + '. ' + option + '</option>');
    }
  }

  var performTest = function(functionNumber) {
    reset(); // Reset previous test
    $("#tests").html(""); //Clean test results
    isNumber = functionsToTest[functionNumber]; // Override the isNumber global function with the one to test
    testSuite(); // Run the test

    // Get test results
    var totalFail = 0;
    var totalPass = 0;
    $("b.fail").each(function() {
      totalFail += Number($(this).html());
    });
    $("b.pass").each(function() {
      totalPass += Number($(this).html());
    });
    $("#testresult").html(totalFail + " of " + (totalFail + totalPass) + " test failed.");

    $("#banner").attr("class", "").addClass(totalFail > 0 ? "fail" : "pass");
  }

  return {
    performTest: performTest,
    fillToTestSelect: fillToTestSelect,
    testSuite: testSuite
  };
}();


$(document).ready(function() {
  testHelper.fillToTestSelect();
  testHelper.performTest(0);

  $("#toTest").change(function() {
    testHelper.performTest($(this).children(":selected").val());
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script>
<script src="https://rawgit.com/Xotic750/testrunner-old/master/testrunner.js" type="text/javascript"></script>
<link href="https://rawgit.com/Xotic750/testrunner-old/master/testrunner.css" rel="stylesheet" type="text/css">
<h1>isNumber Test Cases</h1>

<h2 id="banner" class="pass"></h2>

<h2 id="userAgent">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11</h2>

<div id="currentFunction"></div>

<div id="selectFunction">
  <label for="toTest" style="font-weight:bold; font-size:Large;">Select function to test:</label>
  <select id="toTest" name="toTest">
  </select>
</div>

<div id="testCode"></div>

<ol id="tests">
  <li class="pass">
    <strong>Integer Literals <b style="color:black;">(0, 10, 10)</b></strong>

    <ol style="display: none;">
      <li class="pass">Negative integer string</li>

      <li class="pass">Zero string</li>

      <li class="pass">Positive integer string</li>

      <li class="pass">Negative integer number</li>

      <li class="pass">Zero integer number</li>

      <li class="pass">Positive integer number</li>

      <li class="pass">Octal integer literal string</li>

      <li class="pass">Octal integer literal</li>

      <li class="pass">Hexadecimal integer literal string</li>

      <li class="pass">Hexadecimal integer literal</li>
    </ol>
  </li>

  <li class="pass">
    <strong>Foating-Point Literals <b style="color:black;">(0, 6, 6)</b></strong>

    <ol style="display: none;">
      <li class="pass">Negative floating point string</li>

      <li class="pass">Positive floating point string</li>

      <li class="pass">Negative floating point number</li>

      <li class="pass">Positive floating point number</li>

      <li class="pass">Exponential notation</li>

      <li class="pass">Exponential notation string</li>
    </ol>
  </li>

  <li class="pass">
    <strong>Non-Numeric values <b style="color:black;">(0, 18, 18)</b></strong>

    <ol style="display: none;">
      <li class="pass">Empty string: false</li>

      <li class="pass">Whitespace characters string: false</li>

      <li class="pass">Tab characters string: false</li>

      <li class="pass">Alphanumeric character string: false</li>

      <li class="pass">Non-numeric character string: false</li>

      <li class="pass">Boolean true literal: false</li>

      <li class="pass">Boolean false literal: false</li>

      <li class="pass">Number with preceding non-numeric characters: false</li>

      <li class="pass">Number with trailling non-numeric characters: false</li>

      <li class="pass">Undefined value: false</li>

      <li class="pass">Null value: false</li>

      <li class="pass">NaN value: false</li>

      <li class="pass">Infinity primitive: false</li>

      <li class="pass">Positive Infinity: false</li>

      <li class="pass">Negative Infinity: false</li>

      <li class="pass">Date object: false</li>

      <li class="pass">Empty object: false</li>

      <li class="pass">Instance of a function: false</li>
    </ol>
  </li>
</ol>

<div id="main">
  This page contains tests for a set of isNumber functions. To see them, take a look at the source.
</div>

<div>
  <p class="result">Tests completed in 0 milliseconds.
    <br>0 tests of 0 failed.</p>
</div>


2
Đây là trong quan điểm của tôi chức năng được bảo vệ nhất; Cái cuối cùng. Câu trả lời được chấp nhận có thể bao gồm 99,99% tất cả các trường hợp nhưng câu hỏi này có thể có 100% trường hợp a) với một chi phí nhỏ.
Samuel

Bạn đã quên "99.999" theo nghĩa đen. Đó là một con số hợp lệ ở tất cả châu Âu ngoại trừ Vương quốc Anh
Andrii Horda

Nó không bị lãng quên, đó không phải là thứ mà tôi coi là số theo nghĩa của số Javascript, OP cũng đã tuyên bốIsNumeric('99,999') => false
Xotic750

34

Vâng, tích hợp isNaN(object)sẽ nhanh hơn nhiều so với bất kỳ phân tích cú pháp regex nào, bởi vì nó được tích hợp và biên dịch, thay vì diễn giải nhanh chóng.

Mặc dù kết quả có phần khác với những gì bạn đang tìm kiếm ( hãy thử ):

                                              // IS NUMERIC
document.write(!isNaN('-1') + "<br />");      // true
document.write(!isNaN('-1.5') + "<br />");    // true
document.write(!isNaN('0') + "<br />");       // true
document.write(!isNaN('0.42') + "<br />");    // true
document.write(!isNaN('.42') + "<br />");     // true
document.write(!isNaN('99,999') + "<br />");  // false
document.write(!isNaN('0x89f') + "<br />");   // true
document.write(!isNaN('#abcdef') + "<br />"); // false
document.write(!isNaN('1.2.3') + "<br />");   // false
document.write(!isNaN('') + "<br />");        // true
document.write(!isNaN('blah') + "<br />");    // false

18

Sử dụng chức năng isNaN. Tôi tin rằng nếu bạn kiểm tra !isNaN(yourstringhere)nó hoạt động tốt cho bất kỳ tình huống nào trong số này.


Lưu ý :! IsNaN (null) == true kể từ Số (null) == 0
Jonathan Lonowski

if (! (x == null | | isNaN (x))) cảnh báo ("isNumeric"); // Nhưng giải pháp này chấp nhận 0x40 nên nó vẫn không phải là điều mà op muốn.
một số

Lưu ý rằng isNaN ("Infinity") === sai, đây có thể không phải là điều bạn muốn (nhưng cũng sẽ không xảy ra trong cuộc sống thực).
Erik Hesselink

16

Kể từ jQuery 1.7, bạn có thể sử dụng jQuery.isNumeric():

$.isNumeric('-1');      // true
$.isNumeric('-1.5');    // true
$.isNumeric('0');       // true
$.isNumeric('0.42');    // true
$.isNumeric('.42');     // true
$.isNumeric('0x89f');   // true (valid hexa number)
$.isNumeric('99,999');  // false
$.isNumeric('#abcdef'); // false
$.isNumeric('1.2.3');   // false
$.isNumeric('');        // false
$.isNumeric('blah');    // false

Chỉ cần lưu ý rằng không giống như những gì bạn nói, 0x89flà một số hợp lệ (hexa)


OP muốn số thập phân hợp lệ , do đó jQuery isNumeric không phù hợp. Nó cũng thất bại với số lượng rất lớn.
RobG

13

Nó có thể được thực hiện mà không có RegExp như

function IsNumeric(data){
    return parseFloat(data)==data;
}

5
Nếu chúng ta đang sử dụng ==, nó sẽ trả về true ngay cả đối với các số được trình bày dưới dạng chuỗi. Vì vậy, "42" sẽ được tính là số hợp lệ trong trường hợp "==" và sẽ được tính là không hợp lệ trong trường hợp ===
Thủy

điều này trả về đúng vào "-0.", "-.0", ".0" và "0."
Janus Troelsen


8
return (input - 0) == input && input.length > 0;

không làm việc cho tôi. Khi tôi đưa ra một cảnh báo và thử nghiệm, input.lengthundefined. Tôi nghĩ rằng không có tài sản để kiểm tra chiều dài số nguyên. Vì vậy, những gì tôi đã làm là

var temp = '' + input;
return (input - 0) == input && temp.length > 0;

Nó hoạt động tốt.


7

Nếu tôi không nhầm, giá trị này phải khớp với bất kỳ giá trị số JavaScript hợp lệ nào, ngoại trừ các hằng số ( Infinity, NaN) và các toán tử ký hiệu +/ -(vì chúng không thực sự là một phần của số theo như tôi nghĩ, chúng là các toán tử riêng biệt):

Tôi cần điều này cho một mã thông báo, trong đó việc gửi số tới JavaScript để đánh giá không phải là một tùy chọn ... Đây chắc chắn không phải là biểu thức chính quy ngắn nhất có thể, nhưng tôi tin rằng nó nắm bắt được tất cả các cú pháp tinh vi hơn của cú pháp số JavaScript.

/^(?:(?:(?:[1-9]\d*|\d)\.\d*|(?:[1-9]\d*|\d)?\.\d+|(?:[1-9]\d*|\d)) 
(?:[e]\d+)?|0[0-7]+|0x[0-9a-f]+)$/i

Số hợp lệ sẽ bao gồm:

 - 0
 - 00
 - 01
 - 10
 - 0e1
 - 0e01
 - .0
 - 0.
 - .0e1
 - 0.e1
 - 0.e00
 - 0xf
 - 0Xf

Số không hợp lệ sẽ là

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0

7

Vấn đề duy nhất tôi gặp phải với câu trả lời của @ CMS là loại trừ NaNvà Infinity, đây là những con số hữu ích cho nhiều tình huống. Một cách để kiểm tra NaNlà kiểm tra các giá trị số không bằng nhau , NaN != NaN! Vì vậy, thực sự có 3 bài kiểm tra bạn muốn xử lý ...

function isNumber(n) {
  n = parseFloat(n);
  return !isNaN(n) || n != n;
}
function isFiniteNumber(n) {
  n = parseFloat(n);
  return !isNaN(n) && isFinite(n);
}    
function isComparableNumber(n) {
  n = parseFloat(n);
  return (n >=0 || n < 0);
}

isFiniteNumber('NaN')
false
isFiniteNumber('OxFF')
true
isNumber('NaN')
true
isNumber(1/0-1/0)
true
isComparableNumber('NaN')
false
isComparableNumber('Infinity')
true

My isComparableNumber khá gần với một câu trả lời tao nhã khác , nhưng xử lý hex và các biểu diễn chuỗi khác của các số.


6

Đối với tôi, đây là cách tốt nhất:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}

Thật không may, đây là trình kiểm tra số STRICT sẽ không thành công cho bất kỳ chuỗi nào chỉ chứa các chữ số, như "0", v.v ...
Arman McHitarian

6

Tôi muốn thêm vào như sau:

1. IsNumeric('0x89f') => true
2. IsNumeric('075') => true

Số hex dương bắt đầu bằng 0xvà số hex âm bắt đầu bằng -0x. Số oct dương bắt đầu bằng 0và số oct âm bắt đầu bằng -0. Điều này có phần lớn những gì đã được đề cập, nhưng bao gồm các số hex và bát phân, khoa học phủ định, Vô cực và đã loại bỏ khoa học thập phân ( 4e3.2không hợp lệ).

function IsNumeric(input){
  var RE = /^-?(0|INF|(0[1-7][0-7]*)|(0x[0-9a-fA-F]+)|((0|[1-9][0-9]*|(?=[\.,]))([\.,][0-9]+)?([eE]-?\d+)?))$/;
  return (RE.test(input));
}

6

Tôi nghĩ rằng hàm parseFloat có thể thực hiện tất cả các công việc ở đây. Hàm bên dưới vượt qua tất cả các bài kiểm tra trên trang này bao gồm isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}

Vâng, tôi cũng đi đến kết luận này. Tôi cũng khá thích cách các mảng được xử lý bằng phương pháp này; một mảng với một giá trị duy nhất được tính là giá trị đó, nhưng mọi thứ khác đều thất bại: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; Nhưng tôi tưởng tượng đó là vấn đề của hương vị!
Mark Birbeck

4

Một vài thử nghiệm để thêm:

IsNumeric('01.05') => false
IsNumeric('1.') => false
IsNumeric('.') => false

Tôi nghĩ ra cái này:

function IsNumeric(input) {
    return /^-?(0|[1-9]\d*|(?=\.))(\.\d+)?$/.test(input);
}

Giải pháp bao gồm:

  • Một dấu hiệu tiêu cực tùy chọn ở đầu
  • Một số không, hoặc một hoặc nhiều chữ số không bắt đầu bằng 0 hoặc không có gì miễn là một khoảng thời gian sau
  • Một khoảng thời gian được theo sau bởi 1 hoặc nhiều số

4

Một giá trị số nguyên có thể được xác minh bởi:

function isNumeric(value) {
    var bool = isNaN(+value));
    bool = bool || (value.indexOf('.') != -1);
    bool = bool || (value.indexOf(",") != -1);
    return !bool;
};

Cách này dễ dàng và nhanh hơn! Tất cả các bài kiểm tra đã được kiểm tra!


4

Đây là phiên bản được cải tiến một chút (có lẽ là cách nhanh nhất hiện có) mà tôi sử dụng thay vì biến thể chính xác của jQuery, tôi thực sự không biết tại sao họ không sử dụng phiên bản này:

function isNumeric(val) {
    return !isNaN(+val) && isFinite(val);
}

Nhược điểm của phiên bản của jQuery là nếu bạn vượt qua một chuỗi với hàng đầu numerics và dấu chữ như "123abc"những parseFloat | parseIntsẽ trích phần số và gửi lại 123, NHƯNG, bảo vệ thứ hai isFinitesẽ thất bại nó anyway. Với toán tử đơn nguyên, +nó sẽ chết trong lần bảo vệ đầu tiên kể từ khi + ném NaN cho các phép lai như vậy :) Một hiệu suất nhỏ nhưng tôi nghĩ rằng một lợi ích ngữ nghĩa vững chắc.


2
Coi chừng unary '+' sẽ gọi valueOf () trên một đối tượng - xem jsfiddle này . Ngoài ra điều này cũng thất bại cho khoảng trắng hàng đầu, cũng như câu trả lời hàng đầu.
Earcam

3

Giải pháp của tôi,

function isNumeric(input) {
    var number = /^\-{0,1}(?:[0-9]+){0,1}(?:\.[0-9]+){0,1}$/i;
    var regex = RegExp(number);
    return regex.test(input) && input.length>0;
}

Nó xuất hiện để làm việc trong mọi tình huống, nhưng tôi có thể sai.


Regex đó sẽ ít gây nhầm lẫn hơn nếu bạn không cần thoát các ký tự, sử dụng ?cho {0,1}\dcho [0-9]. Ngoài ra +và sau đó gói nó với (?:){0,1}, bạn cũng có thể sử dụng *và quên các nhóm bắt (không).
alex

3

Tôi đang sử dụng giải pháp đơn giản hơn:

function isNumber(num) {
    return parseFloat(num).toString() == num
}

5
điều này sẽ thất bại trên bất cứ thứ gì có 0 0 cuối cùng. ví dụ: "10.0"
Janus Troelsen

3

Điều này nên làm việc. Một số chức năng được cung cấp ở đây là thiếu sót, cũng nên nhanh hơn bất kỳ chức năng nào khác ở đây.

        function isNumeric(n)
        {
            var n2 = n;
            n = parseFloat(n);
            return (n!='NaN' && n2==n);
        }

Giải thích:

Tạo một bản sao của chính nó, sau đó chuyển đổi số thành float, sau đó so sánh nó với số ban đầu, nếu nó vẫn là một số, (cho dù là số nguyên hay float), và khớp với số ban đầu, điều đó có nghĩa, đó thực sự là một số.

Nó hoạt động với các chuỗi số cũng như số đơn giản. Không hoạt động với số thập lục phân.

Cảnh báo: sử dụng có nguy cơ của riêng bạn, không có bảo đảm.


4
sử dụng có nguy cơ của riêng bạn, không đảm bảo tôi sẽ không sử dụng mã mà tác giả không tin tưởng;)
alex

1
@Alex, Ít nhất là có ý kiến ​​của riêng bạn về mọi thứ. Đừng chỉ trích mọi lúc.
Stewart Mbofana

3

Không có câu trả lời nào trả về falsechuỗi trống, cách khắc phục cho ...

function is_numeric(n)
{
 return (n != '' && !isNaN(parseFloat(n)) && isFinite(n));
}

3

Để kiểm tra xem một biến có chứa một số hợp lệ không chứ không chỉ là một Chuỗi trông giống như một số, Number.isFinite(value) có thể được sử dụng.

Đây là một phần của ngôn ngữ kể từ ES2015

Ví dụ:

Number.isFinite(Infinity)   // false
Number.isFinite(NaN)        // false
Number.isFinite(-Infinity)  // false

Number.isFinite(0)          // true
Number.isFinite(2e64)       // true

Number.isFinite('0')        // false
Number.isFinite(null)       // false

1
Tôi đoán rất nhiều người đề cập đến câu hỏi này để phân tích cú pháp đầu vào của người dùng, thường là một chuỗi . Câu trả lời này không thành công trong những trường hợp đó, vì bạn liệt kê chính xác trong các ví dụ, ví dụNumber.isFinite('0') -> false
Michael Haren

Bạn hoàn toàn đúng. Tôi đã cố gắng để làm cho điều này rõ ràng lên phía trước.
adius

3
function inNumeric(n){
   return Number(n).toString() === n;
}

Nếu n là số Number(n)sẽ trả về giá trị số và toString()sẽ biến nó trở lại thành một chuỗi. Nhưng nếu n không phải là số Number(n)sẽ trả về NaNvì vậy nó sẽ không khớp với bản gốcn


Mặc dù đoạn mã này có thể giải quyết câu hỏi, bao gồm một lời giải thích thực sự giúp cải thiện chất lượng bài đăng của bạn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai và những người đó có thể không biết lý do cho đề xuất mã của bạn. Xin vui lòng cố gắng không làm đông mã của bạn với các bình luận giải thích, vì điều này làm giảm khả năng đọc của cả mã và các giải thích!
Tạm biệt StackExchange

2

Tôi nhận ra điều này đã được trả lời nhiều lần, nhưng sau đây là một ứng cử viên sáng giá có thể hữu ích trong một số tình huống.

cần lưu ý rằng nó giả sử rằng '.42' KHÔNG phải là số và '4.' KHÔNG phải là một số, vì vậy điều này nên được tính đến.

function isDecimal(x) {
  return '' + x === '' + +x;
}

function isInteger(x) {
  return '' + x === '' + parseInt(x);
}

Các isDecimalbài kiểm tra sau:

function testIsNumber(f) {
  return f('-1') && f('-1.5') && f('0') && f('0.42')
    && !f('.42') && !f('99,999') && !f('0x89f')
    && !f('#abcdef') && !f('1.2.3') && !f('') && !f('blah');
}

Ý tưởng ở đây là mọi số hoặc số nguyên đều có một biểu diễn chuỗi "chính tắc" và mọi đại diện không chính tắc nên bị loại bỏ. Vì vậy, chúng tôi chuyển sang một số và quay lại, và xem kết quả có phải là chuỗi gốc không.

Liệu các chức năng này có hữu ích cho bạn hay không tùy thuộc vào trường hợp sử dụng. Một tính năng là các chuỗi riêng biệt đại diện cho các số riêng biệt (nếu cả hai đều vượt quaisNumber() bài kiểm tra).

Điều này có liên quan, ví dụ như cho các số như tên thuộc tính đối tượng.

var obj = {};
obj['4'] = 'canonical 4';
obj['04'] = 'alias of 4';
obj[4];  // prints 'canonical 4' to the console.

2

Chức năng xác thực thư viện Inoutild

Bằng cách mở rộng nó, trường được xác nhận

1) số

self.number = ko.observable(numberValue).extend ({số: đúng}) ;

TestCase

numberValue = '0.0'    --> true
numberValue = '0'      --> true
numberValue = '25'     --> true
numberValue = '-1'     --> true
numberValue = '-3.5'   --> true
numberValue = '11.112' --> true
numberValue = '0x89f'  --> false
numberValue = ''       --> false
numberValue = 'sfsd'   --> false
numberValue = 'dg##$'  --> false

2) chữ số

self.number = ko.observable(numberValue).extend ({chữ số: đúng}) ;

TestCase

numberValue = '0'      --> true
numberValue = '25'     --> true
numberValue = '0.0'    --> false
numberValue = '-1'     --> false
numberValue = '-3.5'   --> false
numberValue = '11.112' --> false
numberValue = '0x89f'  --> false
numberValue = ''       --> false
numberValue = 'sfsd'   --> false
numberValue = 'dg##$'  --> false

3) tối thiểu và tối đa

self.number = ko.observable(numberValue).extend ({min: 5}). extend ({max: 10}) ;

Trường này chỉ chấp nhận giá trị từ 5 đến 10

TestCase

numberValue = '5'    --> true
numberValue = '6'    --> true
numberValue = '6.5'  --> true
numberValue = '9'    --> true
numberValue = '11'   --> false
numberValue = '0'    --> false
numberValue = ''    --> false

2

Nếu bạn cần xác thực một bộ số thập phân đặc biệt, bạn có thể sử dụng javascript đơn giản này:

http://codesheet.org/codesheet/x1kI7hAD

<input type="text" name="date" value="" pattern="[0-9]){1,2}(\.){1}([0-9]){2}" maxlength="6" placeholder="od npr.: 16.06" onchange="date(this);" />

Javascript:

function date(inputField) {        
  var isValid = /^([0-9]){1,2}(\.){1}([0-9]){2}$/.test(inputField.value);   
  if (isValid) {
    inputField.style.backgroundColor = '#bfa';
  } else {
    inputField.style.backgroundColor = '#fba';
  }
  return isValid;
}

2

isNumeric=(el)=>{return Boolean(parseFloat(el)) && isFinite(el)}

Không có gì khác nhau nhưng chúng ta có thể sử dụng hàm tạo Boolean

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.