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>
JBa
źródło
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")
pranag
źródło
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.

krisk
źródło
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
}
Blake Regalia
źródło
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;
};
Walter Roman
źródło
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.
    }
}
nie
źródło
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);
}
Marcio Mazzucato
źródło
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);
Phil
źródło
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

Jhankar Mahbub
źródło
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
użytkownik603749
źródło
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
if(Number.isInteger(Number(data))){
    //-----
}
Gość
źródło
1
Ten sam komentarz, jak poniżej: Nieobsługiwany przez IE i Safari .
crisscross,
@crisscross Teraz obsługiwane przez wszystko oprócz IE, co stanowi problem tylko w przypadku obsługi starszych systemów operacyjnych.
faintsignal
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
Arsen Aleksanyan
źródło
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.

noce
źródło
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
Arun Joshla
źródło
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.

gavenkoa
źródło
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ę.

gbozee
źródło
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');
}
Hemant
źródło
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!");
}
Elliot Bonneville
źródło
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;
};
zangw
źródło
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.

Charles Chu
źródło
3

Po prostu spróbuj tego:

let number = 5;
if (Number.isInteger(number)) {
    //do something
}
Jan WebDev
źródło
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
ferhrosa
źródło
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)) )

vsync
źródło
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+''));
}
macloving
źródło
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;
};
Golo Roden
źródło
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;

    }
Muhammed Rafiq
źródło
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.

DanielL
źródło
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);
Wasyl Gutnyk
źródło
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");
}
Adeojo Emmanuel IMM
źródło
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.

jahu
źródło