Jak sprawdzić, czy zmienna jest liczbą całkowitą w JavaScript?


405

Jak sprawdzić, czy zmienna jest liczbą całkowitą w JavaScript i wysłać alert, jeśli nie jest? Próbowałem tego, ale to nie działa:

<html>
    <head>
        <script type="text/javascript">
            var data = 22;
            alert(NaN(data));
        </script>
    </head>
</html>

2
Jedną z możliwości jest tutaj użycie parseInt.
Paul

2
jsben.ch/#/htLVw - punkt odniesienia dla typowych sposobów na zrobienie tego
EscapeNetscape

Wszystkie odpowiedzi tutaj są naprawdę nieaktualne. Dzisiaj polecam pozostawanie Number.isIntegerprzy najmniej hackującym sposobie.
Benjamin Gruenbaum,

@Benjamim co jeśli liczba jest ciągiem, który można przekonwertować na liczbę całkowitą? a w HTML wszystko jest łańcuchem .. więc Number.isInteger („69”) ma wartość false
joedotnot

Odpowiedzi:


344

Użyj operatora === ( ścisła równość ) jak poniżej,

if (data === parseInt(data, 10))
    alert("data is integer")
else
    alert("data is not an integer")

95
to liczy NaN jako liczbę całkowitą. działa również gorzej w stosunku do mojej metody. jsperf.com/numbers-and-integers
Blake Regalia

2
jeśli uruchomisz przykład za pomocą powyższego kodu, zostanie on ostrzeżony jako liczba całkowita, a drugi jako nie liczba całkowita, co jest przypadkiem ... w przypadku NaN również typ NaN różni się od typu zwracanej wartości pareInt () .....
pranag

1
mógłbyś trochę rozwinąć? „przykład” pokazuje tylko, że użycie parseInt daje gorszą wydajność niż użycie operatora typeof słowa kluczowego i modułu. ale rozumiem, o co ci teraz chodzi (NaN! = NaN)
Blake Regalia

4
@connorbode w javascript wszystkie liczby mają ten sam typ (nie ma liczby zmiennoprzecinkowej ani podwójnej), więc 2.0 === 2ponieważ niepotrzebny po przecinku jest po prostu inną reprezentacją tej samej liczby, a zatem parseInt(2.0) === 2.0odpowiada temu, parseInt(2) === 2co jest prawdą
Michael Theriot

1
@BlakeRegalia: Chociaż jego metoda jest szybka , nie przekazuje wszystkich możliwych wartości z tej odpowiedzi: stackoverflow.com/a/14794066/843732
c00000fd

506

To zależy, czy chcesz też rzutować ciągi jako potencjalne liczby całkowite?

To wystarczy:

function isInt(value) {
  return !isNaN(value) && 
         parseInt(Number(value)) == value && 
         !isNaN(parseInt(value, 10));
}

Z operacjami bitowymi

Prosta analiza i sprawdzenie

function isInt(value) {
  var x = parseFloat(value);
  return !isNaN(value) && (x | 0) === x;
}

Zwarcie i zapisanie operacji parsowania:

function isInt(value) {
  if (isNaN(value)) {
    return false;
  }
  var x = parseFloat(value);
  return (x | 0) === x;
}

A może oba w jednym ujęciu:

function isInt(value) {
  return !isNaN(value) && (function(x) { return (x | 0) === x; })(parseFloat(value))
}

Testy:

isInt(42)        // true
isInt("42")      // true
isInt(4e2)       // true
isInt("4e2")     // true
isInt(" 1 ")     // true
isInt("")        // false
isInt("  ")      // false
isInt(42.1)      // false
isInt("1a")      // false
isInt("4e2a")    // false
isInt(null)      // false
isInt(undefined) // false
isInt(NaN)       // false

Oto skrzypce: http://jsfiddle.net/opfyrqwp/28/

Wydajność

Testy wykazały, że rozwiązanie zwarciowe ma najlepszą wydajność (ops / s).

// Short-circuiting, and saving a parse operation
function isInt(value) {
  var x;
  if (isNaN(value)) {
    return false;
  }
  x = parseFloat(value);
  return (x | 0) === x;
}

Oto punkt odniesienia: http://jsben.ch/#/htLVw

Jeśli masz ochotę na krótszą, tępą formę zwarcia:

function isInt(value) {
  var x;
  return isNaN(value) ? !1 : (x = parseFloat(value), (0 | x) === x);
}

Oczywiście proponuję, aby zajął się tym minizator.


4
@krisk - Upvoted dla wielu rozwiązań. Przeprowadził także szybki test na 4 podanych przez ciebie wariantach: jsperf.com/tfm-is-integer - i stwierdził, że rozwiązanie zwarciowe ma najlepszą wydajność.
tfmontague

1
Zwraca wartość false w dniu 209999999999999999: - (
jkucharovic

1
@jkucharovic winowajcą jest bitowy operator OR. Użycie wersji niebitowej zwróci wartość true.
krisk

1
To sprawia, że ​​„2” oceniono na prawdę
cyberwombat

1
@cyberwombat dobrze, że to liczba dziesiętna 2.0 :-)
Kuba Beránek

120

Zakładając, że nic nie wiesz o omawianej zmiennej, powinieneś przyjąć następujące podejście:

if(typeof data === 'number') {
    var remainder = (data % 1);
    if(remainder === 0) {
        // yes, it is an integer
    }
    else if(isNaN(remainder)) {
        // no, data is either: NaN, Infinity, or -Infinity
    }
    else {
        // no, it is a float (still a number though)
    }
}
else {
    // no way, it is not even a number
}

Krótko mówiąc:

if(typeof data==='number' && (data%1)===0) {
    // data is an integer
}

8
Co masz na myśli? To sprawdza typy danych w javascript, "1.0"jest ciągiem, a zatem nie jest liczbą. W przeciwnym razie 1będzie wartość zmiennej, jeśli ustawisz ją w ten sposób var my_var=1.0;, która jest poprawnie identyfikowana przez tę funkcję jako liczba całkowita.
Blake Regalia,

4
Wkrótce Number.isInteger()będzie działać ... do tego czasu jest to dobry sposób na zrobienie tego
Claudiu

Number.isInteger nie działa dla mnie. Muszę robić coś złego. Rozwiązanie Blake% 1 działa idealnie.
mcmacerson

104

Number.isInteger() wydaje się być właściwą drogą.

MDN dostarczył również następujący polifill dla przeglądarek nieobsługujących Number.isInteger(), głównie dla wszystkich wersji IE.

Link do strony MDN

Number.isInteger = Number.isInteger || function(value) {
    return typeof value === "number" && 
           isFinite(value) && 
           Math.floor(value) === value;
};

2
MDN ma test na 9007199254740992 usunięty
Bernhard Döbler

2
To najprostsza i „poprawna” odpowiedź. Mam na myśli, że JavaScript ma już metodę sprawdzania liczby całkowitej. Nie musisz pisać nowego. isNaN () sprawdza numeryczność, a nie liczbę całkowitą.
globewalldesk

66

Możesz sprawdzić, czy numer ma resztę:

var data = 22;

if(data % 1 === 0){
   // yes it's an integer.
}

Pamiętaj, że jeśli wprowadzony tekst może być również tekstem i chcesz najpierw sprawdzić, to nie jest, możesz najpierw sprawdzić typ:

var data = 22;

if(typeof data === 'number'){
     // yes it is numeric

    if(data % 1 === 0){
       // yes it's an integer.
    }
}

3
@Erwinus: Uruchom 0 % 1 === 0w konsoli. Zwraca truejako 0 % 1zwroty 0.
Nie,

Czy spróbowałeś w IE ;-)
Codebeat

1
@Erwinus: 0 % 1zwraca 0w trybie zgodności IE9, IE8 i IE7.
Nie,

Wypróbuj w prawdziwym starym IE. poza tym zawsze jest dobrym sposobem programowania, aby sprawdzić zero i nie polegać na przeglądarce, co robić.
Codebeat

62
@Erwinus: Myślę, że pomieszałeś swoje fakty. Błąd dzielenia przez zero powstaje, gdy dzielisz przez zero, a nie, gdy dzielisz zero przez liczbę. W ogóle nie ma to nic wspólnego z wersją IE.
Nie,

22

Możesz użyć prostego wyrażenia regularnego:

function isInt(value) {
    var er = /^-?[0-9]+$/;
    return er.test(value);
}

15

Po pierwsze, NaN jest „liczbą” (tak, wiem, że to dziwne, po prostu z nim walcz), a nie „funkcją”.

Musisz sprawdzić zarówno, czy typ zmiennej jest liczbą, jak i liczbę całkowitą, użyłbym modułu.

alert(typeof data === 'number' && data%1 == 0);

2
powinno być: alert (typeof data == „number” && (data == 0 || data% 1 == 0)); aby uniknąć dzielenia przez zero.
Codebeat

19
@Erwinus 0% 1 jest nadal dzielone przez 1.
Phil

@Phil, (0 == 0 || 0 % 1 == 0)oceni do true.
tomekwi

Och, nawiasem mówiąc, 0 % 1 == 0ocenia też true! %to nie podział!
tomekwi

13

Zachowaj ostrożność podczas korzystania

num% 1

pusty ciąg ('') lub wartość logiczna (prawda lub fałsz) zwróci jako liczbę całkowitą. Możesz tego nie chcieć

false % 1 // true
'' % 1 //true

Number.isInteger (dane)

Number.isInteger(22); //true
Number.isInteger(22.2); //false
Number.isInteger('22'); //false

wbudowana funkcja w przeglądarce. Dosnt obsługuje starsze przeglądarki

Alternatywy:

Math.round(num)=== num

Jednak Math.round () również zawiedzie w przypadku pustych ciągów znaków i wartości logicznych


8

Aby sprawdzić, czy liczba całkowita taka jak plakat chce:

if (+data===parseInt(data)) {return true} else {return false}

notice + przed danymi (konwertuje ciąg na liczbę), a === dla dokładności.

Oto przykłady:

data=10
+data===parseInt(data)
true

data="10"
+data===parseInt(data)
true

data="10.2"
+data===parseInt(data)
false

6
To wydaje się być najmądrzejszym rozwiązaniem dla mojego przypadku (gdzie nie mam nic przeciwko, jeśli jest to liczba całkowita w ciągu). Jednak: dlaczego po prostu nie pójść return (+data===parseInt(data))?
Szwajcarski pan


6

Najprostsze i najczystsze rozwiązanie sprzed ECMAScript-6 (które jest również wystarczająco solidne, aby zwrócić wartość false, nawet jeśli do funkcji zostanie przekazana wartość nienumeryczna, taka jak łańcuch lub null):

function isInteger(x) { return (x^0) === x; } 

Działa również następujące rozwiązanie, choć nie tak eleganckie jak powyższe:

function isInteger(x) { return Math.round(x) === x; }

Zauważ, że Math.ceil () lub Math.floor () mogą być używane równie dobrze (zamiast Math.round ()) w powyższej implementacji.

Lub alternatywnie:

function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0); }

Jednym dość powszechnym niepoprawnym rozwiązaniem jest:

function isInteger(x) { return parseInt(x, 10) === x; }

Chociaż to podejście oparte na analizie składni będzie działało dobrze dla wielu wartości x, gdy x stanie się dość duży, nie będzie działać poprawnie. Problem polega na tym, że parseInt () wymusza swój pierwszy parametr na łańcuch przed analizowaniem cyfr. Dlatego, gdy liczba stanie się wystarczająco duża, jej reprezentacja ciągu zostanie przedstawiona w postaci wykładniczej (np. 1e + 21). W związku z tym parseInt () spróbuje wówczas parsować 1e + 21, ale przestanie analizować, gdy osiągnie znak e, a zatem zwróci wartość 1. Uwaga:

> String(1000000000000000000000)
'1e+21'

> parseInt(1000000000000000000000, 10)
1

> parseInt(1000000000000000000000, 10) === 1000000000000000000000
false

6

Dlaczego nikt nie wspomniał Number.isInteger()?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger

Działa idealnie dla mnie i rozwiązuje problem z NaNpoczątkiem liczby.


1
Pamiętaj, że jest to ES6, więc starsze przeglądarki (takie jak IE <= 11) nie obsługują go. Dokumenty powyżej zawierają polifill.
biskup

Ktoś wspomniał Number.isInteger(), 3,5 roku przed tobą: stackoverflow.com/a/27424770/5208540
Alex Stragies

jeśli mamy zamiar złapać wartość z wejścia, to sprawdź, Number.isInteger zawsze zwróci false, ponieważ wartość wejściowa jest typu danych typu string
Shinigamae

6

W ES6 2 dodano nowe metody dla obiektu liczbowego.

W nim metoda Number.isInteger () zwraca true, jeśli argument jest liczbą całkowitą.

Przykładowe użycie:

Number.isInteger(10);        // returns true
Number.isInteger(10.5);      // returns false

4

Standard ECMA-262 6.0 (ES6) obejmuje funkcję Number.isInteger .

Aby dodać obsługę starej przeglądarki, zdecydowanie polecam użycie silnego i wspieranego przez społeczność rozwiązania:

https://github.com/paulmillr/es6-shim

która jest biblioteką czystych wypełniaczy JS ES6 .

Zauważ, że ta biblioteka wymaga es5-shim, po prostu postępuj zgodnie z README.md.


4

Możesz spróbować, Number.isInteger(Number(value))jeśli np. valueMoże być liczbą całkowitą w postaci ciągu, var value = "23"i chcesz to ocenić true. Unikaj prób, Number.isInteger(parseInt(value))ponieważ nie zawsze zwróci prawidłową wartość. np. jeśli var value = "23abc"i użyjesz parseIntimplementacji, nadal zwróci wartość true.

Ale jeśli chcesz ściśle liczb całkowitych, prawdopodobnie Number.isInteger(value)powinieneś załatwić sprawę.


1
Zauważ, że nie jest to obsługiwane przez IE; jak stwierdzono tutaj w dokumencie , mój skrypt został zatrzymany z tego powodu, szczególnie jeśli var, który sprawdzasz, jest niezdefiniowany
mikewasmike

4
var x = 1.5;
if(!isNaN(x)){
 console.log('Number');
 if(x % 1 == 0){
   console.log('Integer');
 }
}else {
 console.log('not a number');
}

3
Po 29 odpowiedziach można się spodziewać nieco więcej wyjaśnień, aby Twoja odpowiedź wyróżniała się ...
brasofilo

3

Sprawdź, czy zmienna jest równa tej samej zmiennej zaokrąglonej do liczby całkowitej, jak poniżej:

if(Math.round(data) != data) {
    alert("Variable is not an integer!");
}

Można bardzo łatwo rozwiązać problem Funkcja ta jest z powrotem truena NaN, po prostu zmienia !=się !==i odwracanie ifbloków. Działa NaNto, ponieważ jest to jedyna wartość w JavaScript, która nie jest sobie równa. Na przykład nowy kod powinien brzmiećif (Math.round(x) === x) { /* x IS an integer! */ }
mgthomas99

3

Poza tym Number.isInteger(). Być może Number.isSafeInteger()jest tu kolejna opcja przy użyciu specyfikacji ES6.

Aby wypełnić polifill Number.isSafeInteger(..)w przeglądarkach starszych niż ES6:

Number.isSafeInteger = Number.isSafeInteger || function(num) {
    return typeof num === "number" && 
           isFinite(num) && 
           Math.floor(num) === num &&
           Math.abs( num ) <= Number.MAX_SAFE_INTEGER;
};

3

Number.isInteger() to najlepszy sposób, jeśli Twoja przeglądarka go obsługuje, jeśli nie, myślę, że jest tak wiele sposobów:

function isInt1(value){
  return (value^0) === value
}

lub:

function isInt2(value){
  return (typeof value === 'number') && (value % 1 === 0); 
}

lub:

function isInt3(value){
  return parseInt(value, 10) === value; 
}

lub:

function isInt4(value){
  return Math.round(value) === value; 
}

teraz możemy przetestować wyniki:

var value = 1
isInt1(value)   // return true
isInt2(value)   // return true
isInt3(value)   // return true
isInt4(value)   // return true

var value = 1.1
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

var value = 1000000000000000000
isInt1(value)   // return false
isInt2(value)   // return true
isInt3(value)   // return false
isInt4(value)   // return true

var value = undefined
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

var value = '1' //number as string
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

Tak więc wszystkie te metody działają, ale gdy liczba jest bardzo duża, parsowanie i operator ^ nie działałyby dobrze.


3

Po prostu spróbuj tego:

let number = 5;
if (Number.isInteger(number)) {
    //do something
}

Funkcja Number.isInteger () nie jest obsługiwana we wszystkich wersjach przeglądarek IE.
SKR

2

Możesz użyć tej funkcji:

function isInteger(value) {
    return (value == parseInt(value));
}

Zwróci true, nawet jeśli wartość jest łańcuchem zawierającym wartość całkowitą.
Tak więc wyniki będą:

alert(isInteger(1)); // true
alert(isInteger(1.2)); // false
alert(isInteger("1")); // true
alert(isInteger("1.2")); // false
alert(isInteger("abc")); // false

2

Moje podejście:

a >= 1e+21Test może przejść tylko dla wartości, która musi być liczbą i bardzo dużą. Z pewnością obejmie to wszystkie przypadki, w przeciwieństwie do innych rozwiązań przedstawionych w tej dyskusji.

a === (a|0)Jeśli argument danej funkcji jest dokładnie (===) taki sam, jak wartość przekształcona bitowo, oznacza to, że argument jest liczbą całkowitą.

a|0zwróci 0dowolną wartość, aktóra nie jest liczbą , a jeśli arzeczywiście jest liczbą, usunie wszystko po przecinku, więc 1.0001stanie się1

function isInteger(a){
    return a >= 1e+21 ? true : a === (a|0)
}

/// tests ///////////////////////////
[
  1,                        // true
  1000000000000000000000,   // true
  4e2,                      // true
  Infinity,                 // true
  1.0,                      // true
  1.0000000000001,          // false
  0.1,                      // false
  "0",                      // false
  "1",                      // false
  "1.1",                    // false
  NaN,                      // false
  [],                       // false
  {},                       // false
  true,                     // false
  false,                    // false
  null,                     // false
  undefined                 // false
].forEach( a => console.log(typeof a, a, isInteger(a)) )


1
Dobry pomysł! Podoba mi się również to, że pokazałeś swoje testy, ale niestety nie uwzględnia to wartości ciągu równej „0”.
Jammer,

Cześć @vsync, Nie celowo. Pierwotnie głosowałem za przyjęciem opinii, ale postanowiłem ją wycofać z powodu mojego poprzedniego komentarza. Musiałem przypadkowo dwukrotnie kliknąć lub coś.
Jammer

1

Możesz użyć wyrażenia regularnego w tym celu:

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


1

Użyj |operatora:

(5.3 | 0) === 5.3 // => false
(5.0 | 0) === 5.0 // => true

Tak więc funkcja testowa może wyglądać następująco:

var isInteger = function (value) {
  if (typeof value !== 'number') {
    return false;
  }

  if ((value | 0) !== value) {
    return false;
  }

  return true;
};

1

To rozwiąże jeszcze jeden scenariusz ( 121. ), kropka na końcu

function isInt(value) {
        var ind = value.indexOf(".");
        if (ind > -1) { return false; }

        if (isNaN(value)) {
            return false;
        }

        var x = parseFloat(value);
        return (x | 0) === x;

    }

1

Dla dodatnich wartości całkowitych bez separatorów:

return ( data !== '' && data === data.replace(/\D/, '') );

Testy 1. jeśli nie są puste i 2. jeśli wartość jest równa wynikowi zastąpienia nie-cyfrowego znaku w jej wartości.


1

Ok mam minus, bo nie opisałem mojego przykładu, więc więcej przykładów :):

Używam wyrażenia regularnego i metody testowej:

var isInteger = /^[0-9]\d*$/;

isInteger.test(123); //true
isInteger.test('123'); // true
isInteger.test('sdf'); //false
isInteger.test('123sdf'); //false

// If u want to avoid string value:
typeof testVal !== 'string' && isInteger.test(testValue);

Dostałem minus prawdopodobnie dlatego, że test nie jest funkcją.
imlokesh

@imlokesh co masz na myśli mówiąc „nie jest funkcją”? oO napisałem, że używam „metody testowej”.
Vasyl Gutnyk

@imlokesh nie ma problemu, po prostu pytam U, ponieważ użyłem go w produkcji :) i myślałem, że znalazłem jakiś błąd :)
Vasyl Gutnyk

1

możesz także spróbować w ten sposób

var data = 22;
if (Number.isInteger(data)) {
    console.log("integer");
 }else{
     console.log("not an integer");
 }

lub

if (data === parseInt(data, 10)){
    console.log("integer");
}else{
    console.log("not an integer");
}

Spowoduje to uzyskanie niewłaściwego wyniku dla data=22.5;. Także obie gałęzie mają console.log("not an integer"):: S
Colin Breame

0

Musiałem sprawdzić, czy zmienna (ciąg lub liczba) jest liczbą całkowitą i użyłem tego warunku:

function isInt(a){
    return !isNaN(a) && parseInt(a) == parseFloat(a);
}

http://jsfiddle.net/e267369d/1/

Niektóre inne odpowiedzi mają podobne rozwiązanie (polegają na parseFloatpołączeniu z isNaN), ale moje powinny być bardziej bezpośrednie i samoobjaśniające.


Edycja: dowiedziałem się, że moja metoda zawodzi w przypadku ciągów zawierających przecinek (np. „1,2”) i zdałem sobie również sprawę, że w moim szczególnym przypadku chcę, aby funkcja zawiodła, jeśli ciąg nie jest prawidłową liczbą całkowitą (powinien zawieść na dowolnym zmiennoprzecinkowym , nawet 1,0). Oto moja funkcja Mk II:

function isInt(a){
    return !isNaN(a) && parseInt(a) == parseFloat(a) && (typeof a != 'string' || (a.indexOf('.') == -1 && a.indexOf(',') == -1));
}

http://jsfiddle.net/e267369d/3/

Oczywiście w przypadku, gdy rzeczywiście potrzebujesz funkcji, aby zaakceptować liczby całkowite (1.0 rzeczy), zawsze możesz usunąć warunek kropki a.indexOf('.') == -1.

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.