javascript - validate - js validation




在JavaScript中驗證十進制數-IsNumeric() (20)

在JavaScript中驗證十進制數的最簡潔,最有效的方法是什麼?

獎勵積分:

  1. 明晰。 解決方案應該干淨簡單。
  2. 跨平台。

測試用例:

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

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()。


@CMS'回答:你的代碼片段在我的機器上使用nodejs的空白案例失敗了。所以我把它與@ joel的答案結合起來:

is_float = function(v) {
    return !isNaN(v) && isFinite(v) &&
        (typeof(v) == 'number' || v.replace(/^\s+|\s+$/g, '').length > 0);
}

我將它與那些浮動的案例進行了單獨測試:

var t = [
        0,
        1.2123,
        '0',
        '2123.4',
        -1,
        '-1',
        -123.423,
        '-123.432',
        07,
        0xad,
        '07',
        '0xad'
    ];

和那些沒有浮點數的情況(包括空白空間和對象/數組):

    var t = [
        'hallo',
        [],
        {},
        'jklsd0',
        '',
        "\t",
        "\n",
        ' '
    ];

一切都按預期工作。也許這有幫助。

完整的源代碼可以在here找到。


雅虎 UI使用此:

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

knockoutJs Inbuild庫驗證函數

通過擴展它,字段得到驗證

1)號碼

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

測試用例

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)數字

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

測試用例

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)最小和最大

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

此字段僅接受5到10之間的值

測試用例

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

使用函數isNaN 。 我相信如果你測試!isNaN(yourstringhere)它適用於任何這些情況。


如果我沒有弄錯的話,這應該匹配任何有效的JavaScript數值,不包括常數( InfinityNaN )和符號運算符+ / - (因為就我而言它們實際上不是數字的一部分,它們是單獨的運算符):

我需要這個用於標記化器,其中將數字發送到JavaScript進行評估不是一個選項...它絕對不是最短的正則表達式,但我相信它捕獲了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

有效數字包括:

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

數字無效

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

對我來說,這是最好的方法:

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

從jQuery 1.7開始,你可以使用api.jquery.com/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

請注意,與您所說的不同, 0x89f是有效數字(hexa)


我對@ CMS的answer唯一的問題是排除了NaN和Infinity,這在許多情況下都是有用的數字。 檢查NaN的一種方法是檢查不相等的數值, NaN != NaN ! 所以你真的想要處理3個測試......

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非常接近另一個優雅的answer ,但處理數字的十六進制和其他字符串表示。


我想補充以下內容:

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

正十六進制數開頭,0x負十六進制數開頭-0x。正oct數開頭,0負oct數開頭-0。這個包含了已經提到的大部分內容,但包括十六進制和八進制數,負科學,無窮大並刪除了十進制科學(4e3.2無效)。

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

我意識到這已被多次回答,但以下是一個不錯的候選人,在某些情況下可能會有用。

應該注意的是,假設'.42'不是數字,'4' 不是數字,所以應該考慮到這一點。

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

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

isDecimal通過下面的測試:

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

這裡的想法是每個數字或整數都有一個“規範”字符串表示,並且每個非規範表示都應該被拒絕。所以我們轉換為數字並返回,並查看結果是否是原始字符串。

這些功能是否對您有用取決於用例。一個特徵是不同的字符串代表不同的數字(如果兩者都通過isNumber()測試)。

這與數字作為對象屬性名稱相關。

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

我正在使用更簡單的解決方案:

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

接受的答案沒有通過你的測試#7,我想這是因為你改變了主意。 所以這是對已接受的答案的回應,我遇到了問題。

在某些項目中,我需要驗證一些數據並儘可能確定它是一個可以在數學運算中使用的javascript數值。

jQuery和其他一些javascript庫已經包含了這樣一個函數,通常稱為isNumeric 。 上還有一篇文章已被廣泛接受作為答案,與上述庫所使用的相同的一般例程。

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

首先,如果參數是長度為1的數組,則上面的代碼將返回true,並且該單個元素是上述邏輯認為是數字的類型。 在我看來,如果它是一個數組,那麼它不是數字。

為了緩解這個問題,我添加了一個檢查來從邏輯中對數組進行折扣

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

當然,您也可以使用Array.isArray ,jquery $.isArray或原型Object.isArray而不是Object.prototype.toString.call(n) !== '[object Array]'

我的第二個問題是負十六進制整數文字字符串(“-0xA” - > -10)未計入數字。 但是,正十六進制整數文字字符串(“0xA” - > 10)被視為數字。 我需要兩個都是有效的數字。

然後我修改了邏輯以考慮到這一點。

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

如果你擔心每次調用函數時都會創建正則表達式,那麼你可以在一個閉包中重寫它,像這樣的東西

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

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

然後,我接受了CMS +30測試用例,在jsfiddle上克隆了測試,添加了我的額外測試用例和我上面提到的解決方案。

它可能無法取代廣泛接受/使用過的答案,但如果這更像是您希望的isNumeric函數的結果,那麼希望這會有所幫助。

編輯:正如Bergi所指出的,還有其他可能被視為數字的對象,白名單比黑名單更好。 考慮到這一點,我會添加標準。

我希望我的isNumeric函數只考慮數字或字符串

考慮到這一點,最好使用它

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

測試解決方案

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>


整數值可以通過以下方式驗證:

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

這種方式更容易,更快! 檢查所有測試!


要添加的幾個測試:

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

我想出了這個:

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

解決方案包括:

  • 一個可選的負號在開頭
  • 單個零,或一個或多個不以0開頭的數字,或者只要一個句點跟隨就沒有任何數字
  • 一個句點後跟一個或多個數字

這是一個小改進的版本(可能是最快的方式),我使用而不是精確的jQuery變體,我真的不知道他們為什麼不使用這個:

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

jQuery版本的缺點是,如果你傳遞帶有前導數字的字符串和像"123abc"那樣的尾隨字母,那麼parseFloat | parseInt parseFloat | parseInt將提取數字分數並返回123,但是,第二個守衛isFinite無論如何都會失敗。 使用一元+運算符,它會在第一個警衛身上消失,因為+投擲NaN用於這樣的混合動力:)有點表現但我認為可靠的語義增益。


沒有任何答案返回false空字符串,修復...

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

要檢查變量是否包含有效數字而不僅僅是一個看起來像數字的字符串,Number.isFinite(value)可以使用。

這是自ES2015以來該語言的ES2015

例子:

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

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

這適用於0x23類型數字。


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

如果n為numeric,Number(n)則返回數值,toString()並將其轉回字符串。但如果n不是數字Number(n)將返回,NaN因此它將與原始匹配n





numbers