Validasi angka desimal dalam JavaScript - IsNumeric ()

2376

Apa cara terbersih dan paling efektif untuk memvalidasi angka desimal dalam JavaScript?

Poin bonus untuk:

  1. Kejelasan. Solusi harus bersih dan sederhana.
  2. Lintas-platform.

Kasus uji:

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
Michael Haren
sumber
256
Hanya catatan 99.999 adalah angka yang valid di Perancis, sama dengan 99.999 dalam format uk / us, jadi jika Anda membaca dalam string dari mengucapkan formulir input maka 99.999 mungkin benar.
Re0sless
79
Koma desimal adalah standar di seluruh Eropa dan Rusia (kecuali Inggris)
Calmarius
90
jQuery 1.7 telah memperkenalkan jQuery.isNumericfungsi utilitas: api.jquery.com/jQuery.isNumeric
Ates Goral
24
jQuery.isNumericakan gagal dalam test case ketujuh OP ( IsNumeric('0x89f') => *false*). Saya tidak yakin apakah saya setuju dengan test case ini.
Tim Lehner

Jawaban:

2898

@Jawab Joel cukup dekat, tetapi akan gagal dalam kasus berikut:

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

Beberapa waktu yang lalu saya harus mengimplementasikan suatu IsNumericfungsi, untuk mengetahui apakah suatu variabel berisi nilai numerik, terlepas dari jenisnya , itu bisa berupa Stringnilai numerik (saya harus mempertimbangkan juga notasi eksponensial, dll.), Sebuah Numberobjek, hampir semua hal bisa diteruskan ke fungsi itu, saya tidak bisa membuat asumsi tipe apa pun, mengurus tipe paksaan (mis. +true == 1;tetapi truetidak boleh dianggap sebagai "numeric").

Saya pikir layak berbagi set +30 unit test yang dibuat untuk banyak implementasi fungsi, dan juga berbagi yang melewati semua tes saya:

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

PS Isnan & isFinite memiliki perilaku membingungkan karena konversi dipaksa untuk nomor. Dalam ES6, Number.isNaN & Number.isFinite akan memperbaiki masalah ini. Ingatlah hal itu saat menggunakannya.


Pembaruan : Begini caranya jQuery melakukannya sekarang (2.2-stable) :

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

Pembaruan : Angular 4.3 :

export function isNumeric(value: any): boolean {
    return !isNaN(value - parseFloat(value));
}
CMS
sumber
26
ini gagal dengan lokal lain tempat kami menggunakan koma desimal, tetapi tambahkan `n = n. ganti (/, /,". "); ' sebelum kembali untuk memperbaikinya.
Zoltan Lengyel
5
@ Rob, perilaku itu disengaja, 2e308 > Number.MAX_VALUEsejak 2e308 == Infinity. Jika Anda menginginkan fungsi yang mengembalikan truejuga untuk nilai infinity positif dan negatif, periksa fungsi No. 2 di dalam suite pengujian . Bersulang.
CMS
39
Omong-omong, unit test sekarang sedang digunakan oleh proyek jQuery
CMS
7
jQuery sekarang juga menggunakan implementasi ini.
RichardTowers
4
Solusinya di sini adalah dengan menggunakan JQuery. Mereka memiliki implementasi yang lebih baik dari ini sekarang: github.com/jquery/jquery/blob/master/src/core.js#L230
Robert Massaioli
337

Arrrgh! Jangan dengarkan jawaban ekspresi reguler. RegEx jijik untuk ini, dan saya tidak hanya berbicara kinerja. Sangat mudah untuk membuat kesalahan yang tidak kentara, tidak mungkin terjadi dengan ekspresi reguler Anda.

Jika Anda tidak dapat menggunakan isNaN(), ini seharusnya bekerja lebih baik:

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

Begini cara kerjanya:

The (input - 0)ekspresi memaksa JavaScript untuk melakukan jenis paksaan nilai masukan Anda; pertama-tama harus ditafsirkan sebagai angka untuk operasi pengurangan. Jika konversi ke nomor gagal, ekspresi akan menghasilkan NaN. Ini numerik hasil ini kemudian dibandingkan dengan nilai asli Anda lulus dalam. Sejak sisi kiri sekarang numerik, jenis paksaan lagi digunakan. Sekarang input dari kedua belah pihak dipaksa untuk jenis yang sama dari nilai asli yang sama, Anda akan berpikir mereka harus selalu sama (selalu benar). Namun, ada aturan khusus yang mengatakan NaNtidak pernah sama dengan NaN, sehingga nilai yang tidak dapat dikonversi ke angka (dan hanya nilai yang tidak dapat dikonversi ke angka) akan menghasilkan false.

Pemeriksaan panjangnya untuk kasus khusus yang melibatkan string kosong. Perhatikan juga bahwa itu jatuh pada tes 0x89f Anda, tetapi itu karena di banyak lingkungan itu cara yang baik untuk mendefinisikan angka literal. Jika Anda ingin menangkap skenario spesifik itu, Anda bisa menambahkan cek tambahan. Bahkan lebih baik, jika itu alasan Anda untuk tidak menggunakan isNaN()maka bungkus saja fungsi Anda sendiri isNaN()yang juga dapat melakukan pemeriksaan tambahan.

Singkatnya, jika Anda ingin tahu apakah suatu nilai dapat dikonversi ke angka, sebenarnya cobalah untuk mengubahnya menjadi angka.


Saya kembali dan melakukan penelitian untuk mengapa string spasi tidak memiliki output yang diharapkan, dan saya pikir saya mengerti sekarang: string kosong dipaksa untuk 0bukan NaN. Cukup memangkas string sebelum pemeriksaan panjang akan menangani kasus ini.

Menjalankan tes unit terhadap kode baru dan hanya gagal pada infinity dan boolean literal, dan satu-satunya waktu yang seharusnya menjadi masalah adalah jika Anda membuat kode (sungguh, siapa yang akan mengetikkan literal dan memeriksa apakah itu numerik? Anda harus tahu ), dan itu akan menghasilkan kode aneh.

Tapi, sekali lagi, satu-satunya alasan untuk menggunakan ini adalah jika karena alasan tertentu Anda harus menghindari isNaN ().

Joel Coehoorn
sumber
28
Ini gagal pada string spasi, misalnya IsNumeric(' '), IsNumeric('\n\t'), dll semua kembalitrue
Bulan Sabit Segar
29
Ini juga akan gagal pada Numberliteral IsNumeric(5) == false;memeriksa set unit test yang saya posting, fungsi ini adalah nomor 16pada test suite. stackoverflow.com/questions/18082/…
CMS
20
Saya tidak percaya tidak ada yang menunjukkan penggunaan ekspresi reguler (ganti) setelah peringatan tentang tidak menggunakan ekspresi reguler ... Memang, penggantian spasi putih lebih sederhana daripada angka parse, tapi masih pasti "icky".
Patrick M
1
@Oriol Itu masalah besar ... tanpa perbaikan keamanan yang dirilis setelah tanggal itu, menjauh dari XP harus menjadi prioritas.
Joel Coehoorn
1
@Oriol XP atau tidak, jika Anda menggunakan IE8 atau lebih rendah Anda menggunakan perangkat lunak yang sudah ketinggalan zaman. Memang XP tidak dapat menjalankan IE9 + jadi gunakan Chrome atau FF. Orang-orang yang hidup di masa lalu menggunakan IE8 adalah kutukan bagi banyak pengembang web. Jika saya dapat memiliki kembali waktu yang saya habiskan untuk memastikan kode yang benar-benar bagus juga berjalan di IE8 ... Bagi saya mengambil kode yang berfungsi di FF dan Chrome dan menambalnya untuk berjalan di IE8 adalah sama praktisnya dengan mengambil jendela 8 yang dapat dieksekusi dan pastikan itu berjalan sama di windows 3.1.
chiliNUT
70

Cara ini tampaknya bekerja dengan baik:

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

Dalam satu baris:

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

Dan untuk mengujinya:

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

Saya meminjam regex itu dari http://www.codetoad.com/javascript/isnumeric.asp . Penjelasan:

/^ 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
Michael Haren
sumber
1
// JUGA HARUS DITAMBAHKAN KE TES ANDA hasil + = (! IsNumeric ('-')? "Pass": "Fail") + ": IsNumeric ('-') => false \ n"; hasil + = (! IsNumeric ('01 ')? "Lulus": "Gagal") + ": IsNumeric ('01') => false \ n"; hasil + = (! IsNumeric ('- 01')? "Lulus": "Gagal") + ": IsNumeric ('- 01') => false \ n"; hasil + = (! IsNumeric ('000')? "Lulus": "Gagal") + ": IsNumeric ('000') => false \ n";
Dan
apa fungsinya? / ^ - {0,1} \ d * \. {0,1} \ d + $ /
call-me
dapat "{0,1}" diganti dengan "?", jadi regexp Anda akan terlihat seperti ini: /^-?\d*\.?\d+$/?
Cloud
bagus dan sederhana.
the-breaker
53

Yahoo! UI menggunakan ini:

isNumber: function(o) {
    return typeof o === 'number' && isFinite(o);
}
camomileCase
sumber
25
Itu lebih memeriksa tipe variabel yang bertentangan dengan isi nomor. Ini juga akan gagal pada angka yang dibuat dengan new Number(1).
alex
4
Seperti yang dikatakan alex, ini sebenarnya tidak menjawab pertanyaan yang diajukan karena ini akan gagal jika o = "1001".
Kasus
50
function IsNumeric(num) {
     return (num >=0 || num < 0);
}

Ini berfungsi untuk nomor tipe 0x23 juga.

pengguna189277
sumber
29
IsNumeric(''), IsNumeric(' '), IsNumeric(true), IsNumeric(false), IsNumeric(null)Kembali truebukan false.
Oriol
49

Jawaban yang diterima gagal dalam tes Anda # 7 dan saya rasa itu karena Anda berubah pikiran. Jadi ini adalah jawaban atas jawaban yang diterima, yang dengannya saya memiliki masalah.

Selama beberapa proyek saya harus memvalidasi beberapa data dan memastikan bahwa itu adalah nilai numerik javascript yang dapat digunakan dalam operasi matematika.

jQuery, dan beberapa perpustakaan javascript lainnya sudah menyertakan fungsi seperti itu, biasanya disebut isNumeric. Ada juga posting tentang stackoverflow yang telah diterima secara luas sebagai jawabannya, rutin umum yang sama yang digunakan oleh perpustakaan yang disebutkan sebelumnya.

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

Pertama, kode di atas akan mengembalikan true jika argumennya adalah array dengan panjang 1, dan elemen tunggal itu merupakan tipe yang dianggap numerik oleh logika di atas. Menurut pendapat saya, jika itu array maka itu bukan numerik.

Untuk mengatasi masalah ini, saya menambahkan tanda centang ke array diskon dari logika

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

Tentu saja, Anda juga bisa menggunakan Array.isArray, jquery $.isArrayatau prototipe Object.isArrayalih-alihObject.prototype.toString.call(n) !== '[object Array]'

Masalah kedua saya adalah bahwa string literal heksadesimal Negatif Heksadesimal ("-0xA" -> -10) tidak dihitung sebagai numerik. Namun, string literal heksadesimal Positif Heksadesimal ("0xA" -> 10) diperlakukan sebagai numerik. Saya perlu keduanya menjadi numerik yang valid.

Saya kemudian memodifikasi logika untuk memperhitungkan ini.

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

Jika Anda khawatir tentang pembuatan regex setiap kali fungsi dipanggil maka Anda bisa menulis ulang dalam penutupan, sesuatu seperti ini

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

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

Saya kemudian mengambil CMS +30 test case dan mengkloning pengujian pada jsfiddle menambahkan test case ekstra saya dan solusi yang saya jelaskan di atas.

Itu mungkin tidak menggantikan jawaban yang diterima secara luas / digunakan tetapi jika ini lebih dari apa yang Anda harapkan sebagai hasil dari fungsi isnumerik Anda maka semoga ini akan membantu.

EDIT: Seperti yang ditunjukkan oleh Bergi , ada objek lain yang mungkin bisa dianggap numerik dan akan lebih baik untuk daftar putih daripada daftar hitam. Dengan pemikiran ini saya akan menambah kriteria.

Saya ingin fungsi isNumeric saya hanya mempertimbangkan Bilangan atau String

Dengan pemikiran ini, akan lebih baik untuk digunakan

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(/^-/, ''));
}

Uji solusinya

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>

Xotic750
sumber
2
Ini menurut saya fungsi yang paling terlindung; yang terakhir. Jawaban yang diterima mungkin mencakup 99,99% dari semua kasus, tetapi yang ini mungkin 100% dari a) kasus dengan overhead kecil.
Samuel
Anda lupa tentang "99.999" Foating-Point literal. Ini adalah angka yang valid di seluruh Eropa kecuali Inggris
Andrii Horda
Itu tidak dilupakan, itu bukan sesuatu yang saya anggap numerik dalam arti angka Javascript, OP juga menyatakanIsNumeric('99,999') => false
Xotic750
34

Ya, built-in isNaN(object)akan jauh lebih cepat daripada parsing regex mana pun, karena itu built-in dan dikompilasi, daripada ditafsirkan dengan cepat.

Meskipun hasilnya agak berbeda dengan yang Anda cari ( coba ):

                                              // 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
travis
sumber
18

Gunakan fungsinya isNaN. Saya percaya jika Anda menguji untuk !isNaN(yourstringhere)itu berfungsi dengan baik untuk semua situasi ini.

bubbassauro
sumber
Catatan:! IsNaN (null) == true karena Number (null) == 0
Jonathan Lonowski
if (! (x == null || isNaN (x))) lansiran ("isNumeric"); // Tapi solusi ini menerima 0x40 jadi itu masih bukan yang diinginkan op.
beberapa
Perhatikan bahwa isNaN ("Infinity") === false, yang mungkin juga bukan yang Anda inginkan (tetapi juga tidak akan terjadi di kehidupan nyata).
Erik Hesselink
16

Sejak jQuery 1.7, Anda dapat menggunakan 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

Perhatikan bahwa tidak seperti apa yang Anda katakan, 0x89fangka yang valid (hexa)

Kuf
sumber
OP menginginkan angka desimal yang valid , jadi jQuery isNumeric tidak cocok. Itu juga gagal untuk jumlah yang sangat besar.
RobG
13

Itu dapat dilakukan tanpa RegExp sebagai

function IsNumeric(data){
    return parseFloat(data)==data;
}
Akuatik
sumber
5
Jika kita menggunakan ==, itu akan mengembalikan true bahkan untuk angka yang ditampilkan sebagai string. Jadi "42" akan dihitung sebagai angka yang valid jika "==" dan akan dihitung sebagai tidak valid dalam kasus ===
Aquatic
ini mengembalikan true pada "-0.", "-.0", ".0" dan "0."
Janus Troelsen
8
return (input - 0) == input && input.length > 0;

tidak bekerja untuk saya. Ketika saya dimasukkan ke dalam peringatan dan diuji, input.lengthadalah undefined. Saya pikir tidak ada properti untuk memeriksa panjang bilangan bulat. Jadi yang saya lakukan adalah

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

Itu bekerja dengan baik.

jayakumar
sumber
7

Jika saya tidak salah, ini harus cocok dengan nilai angka JavaScript yang valid, tidak termasuk konstanta ( Infinity, NaN) dan operator tanda +/ -(karena mereka sebenarnya bukan bagian dari nomor sejauh yang saya ketahui, mereka adalah operator terpisah):

Saya memerlukan ini untuk tokenizer, di mana mengirim nomor ke JavaScript untuk evaluasi bukan pilihan ... Ini jelas bukan ekspresi reguler sesingkat mungkin, tapi saya percaya itu menangkap semua seluk-beluk halus sintaksis nomor 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

Nomor yang valid meliputi:

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

Angka yang tidak valid adalah

 - 00e1
 - 01e1
 - 00.0
 - 00x0
 - .
 - .e0
Jonathan Spooner
sumber
7

Satu-satunya masalah yang saya miliki dengan jawaban @ CMS adalah pengecualian NaNdan Infinity, yang merupakan angka berguna untuk banyak situasi. Salah satu cara untuk memeriksa NaNadalah dengan memeriksa nilai numerik yang tidak sama dengan diri mereka sendiri NaN != NaN,! Jadi sebenarnya ada 3 tes yang ingin Anda lakukan ...

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

IsComparableNumber saya cukup dekat dengan jawaban elegan lain , tetapi menangani hex dan representasi string angka lainnya.

hobs
sumber
6

Bagi saya, ini adalah cara terbaik:

isNumber : function(v){
   return typeof v === 'number' && isFinite(v);
}
InsertNameHere
sumber
Sayangnya, ini adalah numeric checker KUAT yang akan gagal untuk string yang berisi huruf numerik saja, seperti "0" dll ...
Arman McHitarian
6

Saya ingin menambahkan yang berikut ini:

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

Bilangan hex positif dimulai dengan 0xdan bilangan hex negatif dimulai dengan -0x. Bilangan oktri positif dimulai dengan 0dan angka ok negatif dimulai dengan -0. Yang ini mengambil sebagian besar dari apa yang telah disebutkan dalam pertimbangan, tetapi termasuk angka hex dan oktal, ilmiah negatif, Infinity dan telah menghilangkan ilmiah desimal ( 4e3.2tidak valid).

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));
}
Marius
sumber
6

Saya pikir fungsi parseFloat dapat melakukan semua pekerjaan di sini. Fungsi di bawah ini lulus semua tes pada halaman ini termasuk isNumeric(Infinity) == true:

function isNumeric(n) {

    return parseFloat(n) == n;
}
John Mikic
sumber
Ya, saya sampai pada kesimpulan ini juga. Saya juga cukup suka cara array diperlakukan menggunakan metode ini; sebuah array dengan nilai tunggal dianggap sebagai nilai itu, tetapi semuanya gagal: IsNumeric([3]) == true; IsNumeric([]) == false; IsNumeric([3, 4]) == false; Tapi saya bayangkan itu masalah selera!
Mark Birbeck
4

Beberapa tes untuk ditambahkan:

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

Saya datang dengan ini:

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

Solusinya meliputi:

  • Tanda negatif opsional di awal
  • Satu nol, atau satu digit atau lebih yang tidak dimulai dengan 0, atau tidak ada selama periode berikutnya
  • Periode yang diikuti oleh 1 atau lebih angka
daging pot
sumber
4

Nilai integer dapat diverifikasi oleh:

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

Cara ini lebih mudah dan lebih cepat! Semua tes diperiksa!

solidarius
sumber
4

Inilah versi yang ditingkatkan sedikit lil (mungkin cara tercepat di luar sana) yang saya gunakan daripada varian jQuery yang tepat, saya benar-benar tidak tahu mengapa mereka tidak menggunakan yang ini:

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

Kelemahan dari versi jQuery adalah bahwa jika Anda melewatkan string dengan memimpin numeric dan trailing huruf seperti "123abc"yang parseFloat | parseIntakan mengekstrak fraksi numerik dan kembali 123, NAMUN, penjaga kedua isFiniteakan gagal pula. Dengan +operator unary itu akan mati pada penjaga pertama sejak + melempar NaN untuk hibrida tersebut :) Sedikit kinerja namun saya pikir keuntungan semantik yang solid.

Arman McHitarian
sumber
2
Berhati-hatilah dengan tanda '+' unary akan memanggil valueOf () pada suatu objek - lihat jsfiddle ini . Juga ini gagal untuk memimpin spasi putih, seperti halnya jawaban terkemuka.
earcam
3

Solusi saya,

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

Tampaknya berfungsi dalam setiap situasi, tetapi saya mungkin salah.

Manusoftar
sumber
Regex itu akan kurang membingungkan jika Anda tidak melarikan diri dari karakter, digunakan ?untuk {0,1}dan \duntuk [0-9]. Juga +dan kemudian membungkusnya dengan (?:){0,1}, Anda mungkin juga menggunakan *dan melupakan kelompok (bukan) yang menangkap.
alex
3

Saya menggunakan solusi yang lebih sederhana:

function isNumber(num) {
    return parseFloat(num).toString() == num
}
Ali Gonabadi
sumber
5
ini akan gagal pada apa pun dengan 0 berlebihan pada akhirnya. contoh: "10.0"
Janus Troelsen
3

Ini seharusnya bekerja. Beberapa fungsi yang disediakan di sini cacat, juga harus lebih cepat daripada fungsi lain di sini.

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

Dijelaskan:

Buat salinannya sendiri, lalu ubah nomornya menjadi float, lalu bandingkan dengan nomor aslinya, jika masih berupa angka, (apakah bilangan bulat atau float), dan cocok dengan angka aslinya, itu berarti, itu memang angka.

Ini bekerja dengan string numerik serta angka polos. Tidak berfungsi dengan angka heksadesimal.

Peringatan: gunakan dengan risiko Anda sendiri, tanpa jaminan.

user532188
sumber
4
gunakan dengan risiko Anda sendiri, tidak ada jaminan saya tidak akan menggunakan kode yang penulis tidak yakin;)
alex
1
@Alex, Setidaknya punya pendapat sendiri tentang banyak hal. Jangan hanya mengkritik sepanjang waktu.
Stewart Mbofana
3

Tidak ada jawaban yang dikembalikan falseuntuk string kosong, perbaikan untuk itu ...

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

Untuk memeriksa apakah variabel berisi angka yang valid dan bukan hanya String yang terlihat seperti angka, Number.isFinite(value)dapat digunakan.

Ini adalah bagian dari bahasa sejak ES2015

Contoh:

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
adius
sumber
1
Saya kira banyak orang merujuk pertanyaan ini untuk mem-parsing input pengguna, yang biasanya berupa string . Jawaban ini gagal dalam kasus-kasus itu, seperti yang Anda sebutkan dengan benar dalam contoh-contoh, misalnyaNumber.isFinite('0') -> false
Michael Haren
Anda sepenuhnya benar. Saya mencoba membuat ini jelas di muka.
adius
3
function inNumeric(n){
   return Number(n).toString() === n;
}

Jika n adalah numerik Number(n)akan mengembalikan nilai numerik dan toString()akan mengubahnya kembali menjadi string. Tetapi jika n bukan numerik Number(n)akan kembali NaNsehingga tidak akan cocok dengan aslinyan

chrmcpn
sumber
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda. Tolong juga cobalah untuk tidak membuat kerumunan kode Anda dengan komentar penjelasan, karena ini mengurangi keterbacaan kode dan penjelasan!
Selamat tinggal StackExchange
2

Saya menyadari ini telah dijawab berkali-kali, tetapi berikut ini adalah kandidat yang layak yang dapat berguna dalam beberapa skenario.

Perlu dicatat bahwa diasumsikan bahwa '.42' BUKAN angka, dan '4.' BUKAN angka, jadi ini harus diperhitungkan.

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

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

The isDecimalmelewati tes berikut:

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');
}

Idenya di sini adalah bahwa setiap bilangan atau bilangan bulat memiliki satu representasi string "kanonik", dan setiap representasi non-kanonik harus ditolak. Jadi kami melemparkan ke nomor dan kembali, dan melihat apakah hasilnya adalah string asli.

Apakah fungsi-fungsi ini berguna bagi Anda tergantung pada use case. Salah satu fitur adalah bahwa string yang berbeda mewakili angka yang berbeda (jika keduanya lulus isNumber()tes).

Ini relevan misalnya untuk angka sebagai nama properti objek.

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

fungsi validasi perpustakaan knockoutJs Inbuild

Dengan memperpanjangnya, bidang tersebut dapat divalidasi

1) angka

self.number = ko.observable(numberValue).extend ({number: true}) ;

Kasus cobaan

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) digit

self.number = ko.observable(numberValue).extend ({digit: true}) ;

Kasus cobaan

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) min dan maks

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

Bidang ini hanya menerima nilai antara 5 dan 10

Kasus cobaan

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

Jika Anda perlu memvalidasi set desimal khusus, Anda dapat menggunakan javascript sederhana ini:

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;
}
studio-klik
sumber
2

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

Tidak ada yang sangat berbeda tetapi kita dapat menggunakan konstruktor Boolean

Shishir Arora
sumber