Sprawdź, czy znak jest liczbą?


104

Muszę sprawdzić, czy justPrices[i].substr(commapos+2,1).

Ciąg to coś takiego: „blabla, 120”

W tym przypadku sprawdzi, czy „0” jest liczbą. Jak można to zrobić?


1
możliwy duplikat tutaj
cctan

1
@cctan To nie jest duplikat. To pytanie dotyczy sprawdzania łańcucha, chodzi o sprawdzanie znaku.
jackocnr

Odpowiedzi:


69

Możesz użyć operatorów porównania, aby sprawdzić, czy mieści się w zakresie cyfr:

var c = justPrices[i].substr(commapos+2,1);
if (c >= '0' && c <= '9') {
    // it is a number
} else {
    // it isn't
}

1
Ja też to wymyśliłem. Dlaczego nikt go nie używa, a zamiast tego dokonuje skomplikowanych porównań? Czy to nie zadziała w niektórych przypadkach?
user826955

44

możesz użyć parseInti potem sprawdzić zisNaN

lub jeśli chcesz pracować bezpośrednio na swoim ciągu, możesz użyć wyrażenia regularnego w następujący sposób:

function is_numeric(str){
    return /^\d+$/.test(str);
}

4
Lub jeszcze prościej, jeśli potrzebujemy sprawdzić tylko jeden znak:function is_numeric_char(c) { return /\d/.test(c); }
jackocnr

1
@jackocnr Twój test zwróci również wartość true dla łańcuchów zawierających więcej niż tylko znak (np is_numeric_char("foo1bar") == true.). jeśli chcesz sprawdzić numeryczny znak, /^\d$/.test(c)byłoby lepszym rozwiązaniem. ale w każdym razie nie było to pytanie :)
Yaron U.

24

EDYCJA: Zaktualizowana odpowiedź Blendera jest właściwą odpowiedzią, jeśli sprawdzasz tylko jeden znak (mianowicie !isNaN(parseInt(c, 10))). Moja odpowiedź poniżej to dobre rozwiązanie, jeśli chcesz przetestować całe ciągi.

Oto isNumericimplementacja jQuery (w czystym JavaScript), która działa na pełnych ciągach :

function isNumeric(s) {
    return !isNaN(s - parseFloat(s));
}

Komentarz do tej funkcji brzmi:

// parseFloat NaNs rzutowane liczbowo fałszywe alarmy (null | true | false | "")
// ... ale błędnie interpretuje ciągi liczb wiodących, szczególnie literały szesnastkowe ("0x ...")
// odejmowanie wymusza nieskończoność na NaN

Myślę, że możemy ufać, że ci faceci spędzili nad tym sporo czasu!

Skomentowane źródło tutaj . Dyskusja dla super maniaków tutaj .


2
To działa, ale jest to przesada w przypadku sprawdzania tylko cyframi (działa z liczbami wielocyfrowymi). Moje rozwiązanie może nie być tak jasne, ale jest znacznie szybsze niż to.
user2486570

18

Zastanawiam się, dlaczego nikt nie opublikował rozwiązania takiego jak:

var charCodeZero = "0".charCodeAt(0);
var charCodeNine = "9".charCodeAt(0);

function isDigitCode(n) {
   return(n >= charCodeZero && n <= charCodeNine);
}

z wywołaniem takim jak:

if (isDigitCode(justPrices[i].charCodeAt(commapos+2))) {
    ... // digit
} else {
    ... // not a digit
}

szukałem dokładnie tego rodzaju rozwiązania - ty
Matthias Herrmann

Możesz usunąć wartość parametru 0 dla charCodeAt, ponieważ 0 jest implikowane, gdy parametr nie jest podany.
Dave de Jong

16

Możesz użyć tego:

function isDigit(n) {
    return Boolean([true, true, true, true, true, true, true, true, true, true][n]);
}

Tutaj porównałem to z akceptowaną metodą: http://jsperf.com/isdigittest/5 . Nie spodziewałem się wiele, więc byłem dość zaskoczony, gdy dowiedziałem się, że zaakceptowana metoda jest znacznie wolniejsza.

Ciekawostką jest to, że o ile zaakceptowana metoda to szybsze poprawne wprowadzenie (np. '5') i wolniejsze dla niepoprawnych (np. 'A'), moja metoda jest dokładnie odwrotna (szybka dla niepoprawnych i wolniejsza dla poprawnych).

Mimo to, w najgorszym przypadku, moja metoda jest 2 razy szybsza niż przyjęte rozwiązanie dla poprawnego wprowadzenia i ponad 5 razy szybsza dla nieprawidłowego wprowadzenia.


5
Uwielbiam tę odpowiedź! Może zoptymalizuj go tak, aby: !!([!0, !0, !0, !0, !0, !0, !0, !0, !0, !0][n]);miał duży potencjał WTF i działa całkiem dobrze (zawodzi 007).
Jonathan

@Jonathan - zobacz moją odpowiedź , metoda nr 4
vsync

7
Zgodnie z tym "length"
Shadow

12

Myślę, że fajnie jest wymyślić sposób rozwiązania tego problemu. Poniżej znajduje się kilka.
(Wszystkie poniższe funkcje zakładają, że argument jest pojedynczym znakiem. Zmień na, n[0]aby go wymusić)

Metoda 1:

function isCharDigit(n){
  return !!n.trim() && n > -1;
}

Metoda 2:

function isCharDigit(n){
  return !!n.trim() && n*0==0;
}

Metoda 3:

function isCharDigit(n){
  return !!n.trim() && !!Number(n+.1); // "+.1' to make it work with "." and "0" Chars
}

Metoda 4:

var isCharDigit = (function(){
  var a = [1,1,1,1,1,1,1,1,1,1];
  return function(n){
    return !!a[n] // check if `a` Array has anything in index 'n'. Cast result to boolean
  }
})();

Metoda 5:

function isCharDigit(n){
  return !!n.trim() && !isNaN(+n);
}

Ciąg testowy:

var str = ' 90ABcd#?:.+', char;
for( char of str ) 
  console.log( char, isCharDigit(char) );

Wyjście metod 1, 2, 3 i 5 truedla " ".
user247702

Dla zabawy zrobiłem ich jsperf, a następnie dodałem charCodeAt()porównanie - które było prawie 4x szybsze - jsperf.com/isdigit3
Rycochet

@Rycochet - dobry. Zakres kodów ASCII to naprawdę najlepszy sposób na testowanie ..
vsync


5

Jeśli testujesz pojedyncze znaki, to:

var isDigit = (function() {
    var re = /^\d$/;
    return function(c) {
        return re.test(c);
    }
}());

zwróci prawdę lub fałsz w zależności od tego, czy c jest cyfrą, czy nie.


4

Proponuję prosty regex.

Jeśli szukasz tylko ostatniego znaku w ciągu:

/^.*?[0-9]$/.test("blabla,120");  // true
/^.*?[0-9]$/.test("blabla,120a"); // false
/^.*?[0-9]$/.test("120");         // true
/^.*?[0-9]$/.test(120);           // true
/^.*?[0-9]$/.test(undefined);     // false
/^.*?[0-9]$/.test(-1);            // true
/^.*?[0-9]$/.test("-1");          // true
/^.*?[0-9]$/.test(false);         // false
/^.*?[0-9]$/.test(true);          // false

A regex jest jeszcze prostszy, jeśli sprawdzasz tylko jeden znak jako dane wejściowe:

var char = "0";
/^[0-9]$/.test(char);             // true

4

Najkrótszym rozwiązaniem jest:

const isCharDigit = n => n < 10;

Możesz również zastosować te:

const isCharDigit = n => Boolean(++n);

const isCharDigit = n => '/' < n && n < ':';

const isCharDigit = n => !!++n;

jeśli chcesz sprawdzić więcej niż 1 chatacter, możesz użyć kolejnych wariantów

Wyrażenie regularne:

const isDigit = n => /\d+/.test(n);

Porównanie:

const isDigit = n => +n == n;

Sprawdź, czy nie jest to NaN

const isDigit = n => !isNaN(n);

3
var Is = {
    character: {
        number: (function() {
            // Only computed once
            var zero = "0".charCodeAt(0), nine = "9".charCodeAt(0);

            return function(c) {
                return (c = c.charCodeAt(0)) >= zero && c <= nine;
            }
        })()
    }
};

1
isNumber = function(obj, strict) {
    var strict = strict === true ? true : false;
    if (strict) {
        return !isNaN(obj) && obj instanceof Number ? true : false;
    } else {
        return !isNaN(obj - parseFloat(obj));
    }
}

wyjście bez trybu ścisłego:

var num = 14;
var textnum = '14';
var text = 'yo';
var nan = NaN;

isNumber(num);
isNumber(textnum);
isNumber(text);
isNumber(nan);

true
true
false
false

wyjście w trybie ścisłym:

var num = 14;
var textnum = '14';
var text = 'yo';
var nan = NaN;

isNumber(num, true);
isNumber(textnum, true);
isNumber(text, true);
isNumber(nan);

true
false
false
false

1

Próbować:

function is_numeric(str){
        try {
           return isFinite(str)
        }
        catch(err) {
            return false
        }
    }


1

Proste rozwiązanie wykorzystujące dynamiczne sprawdzanie typów języka:

function isNumber (string) {
   //it has whitespace
   if(string.trim() === ''){
     return false
   }
   return string - 0 === string * 1
}

zobacz poniższe przypadki testowe


0

To wydaje się działać:

Wiązanie statyczne:

String.isNumeric = function (value) {
    return !isNaN(String(value) * 1);
};

Oprawa prototypowa:

String.prototype.isNumeric = function () {
    return !isNaN(this.valueOf() * 1);
};

Sprawdza pojedyncze znaki, a także całe ciągi, aby zobaczyć, czy są numeryczne.




0

Możesz spróbować (zadziałało w moim przypadku)

Jeśli chcesz sprawdzić, czy pierwszy znak łańcucha jest liczbą int:

if (parseInt(YOUR_STRING.slice(0, 1))) {
    alert("first char is int")
} else {
    alert("first char is not int")
}

Jeśli chcesz sprawdzić, czy znak jest liczbą int:

if (parseInt(YOUR_CHAR)) {
    alert("first char is int")
} else {
    alert("first char is not int")
}

0

Ta funkcja działa dla wszystkich przypadków testowych, które udało mi się znaleźć. Jest również szybszy niż:

function isNumeric (n) {
  if (!isNaN(parseFloat(n)) && isFinite(n) && !hasLeading0s(n)) {
    return true;
  }
  var _n = +n;
  return _n === Infinity || _n === -Infinity;
}

var isIntegerTest = /^\d+$/;
var isDigitArray = [!0, !0, !0, !0, !0, !0, !0, !0, !0, !0];

function hasLeading0s(s) {
  return !(typeof s !== 'string' ||
    s.length < 2 ||
    s[0] !== '0' ||
    !isDigitArray[s[1]] ||
    isIntegerTest.test(s));
}
var isWhiteSpaceTest = /\s/;

function fIsNaN(n) {
  return !(n <= 0) && !(n > 0);
}

function isNumber(s) {
  var t = typeof s;
  if (t === 'number') {
    return (s <= 0) || (s > 0);
  } else if (t === 'string') {
    var n = +s;
    return !(fIsNaN(n) || hasLeading0s(s) || !(n !== 0 || !(s === '' || isWhiteSpaceTest.test(s))));
  } else if (t === 'object') {
    return !(!(s instanceof Number) || fIsNaN(+s));
  }
  return false;
}

function testRunner(IsNumeric) {
  var total = 0;
  var passed = 0;
  var failedTests = [];

  function test(value, result) {
    total++;
    if (IsNumeric(value) === result) {
      passed++;
    } else {
      failedTests.push({
        value: value,
        expected: result
      });
    }
  }
  // true
  test(0, true);
  test(1, true);
  test(-1, true);
  test(Infinity, true);
  test('Infinity', true);
  test(-Infinity, true);
  test('-Infinity', true);
  test(1.1, true);
  test(-0.12e-34, true);
  test(8e5, true);
  test('1', true);
  test('0', true);
  test('-1', true);
  test('1.1', true);
  test('11.112', true);
  test('.1', true);
  test('.12e34', true);
  test('-.12e34', true);
  test('.12e-34', true);
  test('-.12e-34', true);
  test('8e5', true);
  test('0x89f', true);
  test('00', true);
  test('01', true);
  test('10', true);
  test('0e1', true);
  test('0e01', true);
  test('.0', true);
  test('0.', true);
  test('.0e1', true);
  test('0.e1', true);
  test('0.e00', true);
  test('0xf', true);
  test('0Xf', true);
  test(Date.now(), true);
  test(new Number(0), true);
  test(new Number(1e3), true);
  test(new Number(0.1234), true);
  test(new Number(Infinity), true);
  test(new Number(-Infinity), true);
  // false
  test('', false);
  test(' ', false);
  test(false, false);
  test('false', false);
  test(true, false);
  test('true', false);
  test('99,999', false);
  test('#abcdef', false);
  test('1.2.3', false);
  test('blah', false);
  test('\t\t', false);
  test('\n\r', false);
  test('\r', false);
  test(NaN, false);
  test('NaN', false);
  test(null, false);
  test('null', false);
  test(new Date(), false);
  test({}, false);
  test([], false);
  test(new Int8Array(), false);
  test(new Uint8Array(), false);
  test(new Uint8ClampedArray(), false);
  test(new Int16Array(), false);
  test(new Uint16Array(), false);
  test(new Int32Array(), false);
  test(new Uint32Array(), false);
  test(new BigInt64Array(), false);
  test(new BigUint64Array(), false);
  test(new Float32Array(), false);
  test(new Float64Array(), false);
  test('.e0', false);
  test('.', false);
  test('00e1', false);
  test('01e1', false);
  test('00.0', false);
  test('01.05', false);
  test('00x0', false);
  test(new Number(NaN), false);
  test(new Number('abc'), false);
  console.log('Passed ' + passed + ' of ' + total + ' tests.');
  if (failedTests.length > 0) console.log({
    failedTests: failedTests
  });
}
testRunner(isNumber)


Naprawiłem przypadek „0”.
c7x43t

0

O ile wiem, najłatwiej jest pomnożyć przez 1:

var character = ... ; // your character
var isDigit = ! isNaN(character * 1);

Mnożenie przez jeden tworzy liczbę z dowolnego ciągu liczbowego (ponieważ masz tylko jeden znak, zawsze będzie to liczba całkowita od 0 do 9) i NaNdla dowolnego innego ciągu.


-1

Po prostu użyj isFinite

const number = "1";
if (isFinite(number)) {
    // do something
}

Zwraca to prawdę dla spacji ""
Michael Bray
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.