Jak sprawdzić, czy liczba jest liczbą zmiennoprzecinkową lub liczbą całkowitą?

717

Jak okaże się, że liczba ta jest floatalbo integer?

1.25 --> float  
1 --> integer  
0 --> integer  
0.25 --> float
coure2011
źródło
47
Rozumiem, o co tu pytasz, ale dla jasności: <nit-pick>JavaScript nie ma różnych liczb całkowitych i liczb zmiennoprzecinkowych. Każda liczba w JavaScript jest tylko Number. </nit-pick>
Matt Ball
4
Czy Infinitywedług ciebie jest liczbą całkowitą czy niecałkowitą? Odpowiedzi tutaj są dość równomiernie rozłożone na ten wynik.
Mike Samuel
11
@MikeSamuel Aby być matematycznie dokładnym: ponieważ nieskończoność nie jest liczbą rzeczywistą, a wszystkie liczby całkowite są liczbami rzeczywistymi, Infinitynie można jej uważać za liczbę całkowitą.
rvighne
@rvighne, pytanie dotyczy „pływaka”, a nie „prawdziwego”. Tak czy inaczej, liczby rzeczywiste nie mają znaczenia, ponieważ komputery mogą reprezentować tylko liczby obliczalne .
Mike Samuel
2
@rvighne, myślę, że zgadzamy się, że fakt, że nieskończoności i NaN nie są liczbami rzeczywistymi, oznacza, że ​​zmiennoprzecinkowe IEEE-754 nie są podzbiorem liczb rzeczywistych. Cała analiza numeryczna oparta na IEEE-754 musi sobie z tym poradzić. To, czego nie rozumiem, to to, jak według ciebie ten fakt determinuje, jak is_integral powinien zachowywać się względem liczności. Osobiście uważam, że ((x% 1) == 0) jest dobrym proxy i jest w pełni określony przez IEEE-754, więc nie trzeba kłócić się o zgodność między różnymi liniami liczbowymi.
Mike Samuel

Odpowiedzi:

1255

zaznacz resztę, dzieląc przez 1:

function isInt(n) {
   return n % 1 === 0;
}

Jeśli nie wiesz, że argument jest liczbą, potrzebujesz dwóch testów:

function isInt(n){
    return Number(n) === n && n % 1 === 0;
}

function isFloat(n){
    return Number(n) === n && n % 1 !== 0;
}

Aktualizacja 2019 5 lat po napisaniu tej odpowiedzi rozwiązanie zostało ustandaryzowane w skrypcie ECMA 2015. Rozwiązanie to jest ujęte w tej odpowiedzi .

Kennebec
źródło
138
Ostrożny, będzie to również powrót prawdziwe dla pusty ciąg, ciąg reprezentujący liczbę całkowitą, true, false, null, pusta tablica, tablica zawierająca jeden numer integralną, tablicę zawierającą ciąg reprezentujący liczbę całkowitą, a może i więcej.
Dagg Nabbit,
17
Fajna sztuczka, ale nieprawidłowa odpowiedź, ponieważ nie sprawdza ona pustego ciągu, ""a 1.0 isInt("");&& isInt(1.0);skutkuje trueobejrzeniem tego demo jsbin.com/elohuq/1/edit
Champ
9
Ina, użycie === jest ogólnie zalecane w porównaniu z ==, ponieważ prowadzi to do większego bezpieczeństwa typu i bardziej przewidywalnego, jednolitego zachowania. Jak stwierdzili poprzedni odpowiadający, ta odpowiedź jest całkowicie, w 100% nieprawidłowa. Wartości null, pusty łańcuch, 1.0 i wiele innych rejestrują się niepoprawnie jako liczby całkowite (nawet przy sprawdzeniu ===).
whoblitz
54
Pytanie dotyczyło tego, jak sprawdzić, czy liczba jest liczbą całkowitą, a nie jak sprawdzić jakąkolwiek wartość.
kennebec
24
Wiele wrogich komentarzy na temat tego, jak nie sprawdza poprawności ciągów. To nie jest część pytania OP. Jeśli przejdę do SO, aby zadać pytanie dotyczące pobrania ostatniego elementu tablicy, a ktoś odpowie function last (array) { return array[array.length - 1]; }, czy to „po prostu źle” czy „Najgorsza odpowiedź na SO”, ponieważ nie sprawdza, czy argument jest najpierw tablicą? Tak, dobra praktyka sprawdzania argumentów, ale to odpowiedzialność programisty. SO odpowiedzi powinny być krótkie i bezpośrednio odpowiadać na pytanie tak jasno, jak to możliwe.
M Miller,
150

Wypróbuj te funkcje, aby sprawdzić, czy wartość jest pierwotną wartością liczbową, która nie ma części ułamkowej i mieści się w granicach wielkości, które można przedstawić jako dokładną liczbę całkowitą.

function isFloat(n) {
    return n === +n && n !== (n|0);
}

function isInteger(n) {
    return n === +n && n === (n|0);
}
Dagg Nabbit
źródło
5
heh awesom exploit, to prawie moje ( n===+naby sprawdzić numerycznie, n|0zaokrąglić), ale z wbudowanymi operatorami. funky
Claudiu
7
@John Hartsock ciąg nigdy nie będzie wartością liczbową. To jest struna. Celem tej funkcji jest sprawdzenie, czy wartość jest wartością liczbową JavaScript, która nie ma części ułamkowej i mieści się w granicach wielkości, które można przedstawić jako dokładną liczbę całkowitą. Jeśli chcesz sprawdzić ciąg znaków, aby sprawdzić, czy zawiera on ciąg znaków reprezentujących liczbę, zadzwoń parseFloat()najpierw.
Pointy,
4
@John Hartsock: nie zwróci prawdy, jeśli nie zostanie przekazany prymityw liczbowy. Myślę, że ma to sens, biorąc pod uwagę nazwy funkcji. Wszystko inne powinno być kandydatem na isString, isBoolean itp., Jeśli takie funkcje są zapisywane.
Dagg Nabbit,
4
@Pointy: zmiennoprzecinkowe o podwójnej precyzji mogą reprezentować wartości całkowite dokładnie do 2 ^ 53. Zależy to więc od tego, czy OP pytał o liczbę całkowitą w sensie matematycznym (liczby całkowite) czy w 32-bitowym znaczeniu danych. Jeśli to drugie, twoje rozwiązanie jest idealne.
djd
8
w javascript operatory bitowe, takie jak |(OR) działają tylko na 32-bitowych liczbach całkowitych ze znakiem. OP nie określa, czy celem jest sprawdzenie podpisanych wartości int32. Więc to nie zadziała z liczbami spoza zakresu. isInteger(5000000000)wróci, falseco jest złe!
Onur Yıldırım
93

Dlaczego nie coś takiego:

var isInt = function(n) { return parseInt(n) === n };
opłaty wojenne
źródło
To jest właściwie rdzeń dobrego rozwiązania dla mnie. Musiałem pozwolić na dodatnie liczby całkowite i nie zezwalać na liczby zmiennoprzecinkowe, ciągi i ujemne liczby całkowite.
Imran-UK
4
To wydaje się znacznie lepszym rozwiązaniem niż inne w tym wątku. Czy społeczność mogłaby być może krytykowana?
sbichenko
5
var y = 1,00; y === parsowanie (y, 10); // zwraca mi to wartość prawdy, która tak naprawdę nie jest tym, czego chcemy.
Whoughton
Jedynym minusem, jaki widzę, jest to, że podana liczba njest konwertowana na ciąg znaków przez parseInt. Zobacz MDN . Ale skorzystam z tego rozwiązania. :)
RhinoDevel
2
@ekussberg: Dlaczego to powinno być fałszywe? 1 to int. a 02, drugi argument, jest ignorowany.
Flimzy
88

Istnieje metoda o nazwie, Number.isInteger()która jest obecnie implementowana we wszystkim oprócz IE. MDN zapewnia również wypełnianie wielu innych przeglądarek:

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

Jednak w przypadku większości przypadków użycia lepiej jest użyć tego, Number.isSafeInteger który również sprawdza, czy wartość jest tak wysoka / niska, że ​​i tak zostaną utracone miejsca dziesiętne. MDN ma do tego również polyfil. (Potrzebujesz również isIntegerwypełnienia powyżej).

if (!Number.MAX_SAFE_INTEGER) {
    Number.MAX_SAFE_INTEGER = 9007199254740991; // Math.pow(2, 53) - 1;
}
Number.isSafeInteger = Number.isSafeInteger || function (value) {
   return Number.isInteger(value) && Math.abs(value) <= Number.MAX_SAFE_INTEGER;
};
paperstreet7
źródło
Działa to również w moim Chrome i prawdopodobnie jest to droga w przyszłości
Dukeatcoding
1
Moim zdaniem najlepsze rozwiązanie.
Automatico,
1
To z polifillem jest najbardziej niezawodnym i prostym rozwiązaniem.
Francesco Pasa
2
@SergeyPanfilov 12.0 ∈ ℤ.
Константин Ван
1
Nie wiem, czy specyfikacja zmieniła się od czasu udzielenia tej odpowiedzi, ale zauważ, że powyższa funkcja nie jest poprawnym polifillem Number.isInteger. Jest to jednak poprawne wypełnienie dla Number.isSafeInteger. Number.isIntegernie powinien sprawdzać, czy liczba jest „bezpieczną liczbą całkowitą”. Zobacz w MDN: isInteger i isSafeInteger .
nunocastromartins
33

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

function isInt(value) {

    var er = /^-?[0-9]+$/;

    return er.test(value);
}

Możesz też skorzystać z poniższych funkcji, w zależności od potrzeb. Są opracowywane przez projekt PHPJS .

is_int() => Sprawdź, czy typ zmiennej jest liczbą całkowitą i czy jej zawartość jest liczbą całkowitą

is_float() => Sprawdź, czy typ zmiennej jest zmiennoprzecinkowy i czy jego zawartość jest zmiennoprzecinkowa

ctype_digit() => Sprawdź, czy typ zmiennej jest łańcuchem i czy jego zawartość ma tylko cyfry dziesiętne

Aktualizacja 1

Teraz sprawdza również liczby ujemne, dziękuję za komentarz @ChrisBartley !

Marcio Mazzucato
źródło
1
Idealny do testowania prostych liczb całkowitych bez znaku.
tothemario
7
Jeden liniowiec:/^[0-9]+$/.test(String(value))
tothemario
Krótszy i nieco mniej czytelny /^[0-9]+$/.test(''+value)
jednowarstwowy
3
Nie obsługuje ujemnych liczb całkowitych. Nie potrzebujesz również operatora trójskładnikowego, ponieważ test () zwraca wartość logiczną. Powinno to zrobić:return /^-?\d+$/.test(String(value));
Chris Bartley
@ChrisBartley, Thanks! Zrobiłem aktualizację, w tym twoje kredyty. Sprawdź, czy teraz wszystko jest w porządku.
Marcio Mazzucato
19

Oto wydajne funkcje, które sprawdzają, czy wartość jest liczbą lub czy można ją bezpiecznie przekonwertować na liczbę:

function isNumber(value) {
    if ((undefined === value) || (null === value)) {
        return false;
    }
    if (typeof value == 'number') {
        return true;
    }
    return !isNaN(value - 0);
}

A dla liczb całkowitych (zwróciłoby wartość false, jeśli wartość jest liczbą zmiennoprzecinkową):

function isInteger(value) {
    if ((undefined === value) || (null === value)) {
        return false;
    }
    return value % 1 == 0;
}

Wydajność polega na tym, że parseInt (lub parseNumber) jest unikany, gdy wartość jest już liczbą. Obie funkcje parsowania zawsze konwertują najpierw na ciąg, a następnie próbują parsować ten ciąg, co byłoby marnotrawstwem, jeśli wartość jest już liczbą.

Dziękujemy innym postom tutaj za dostarczenie dalszych pomysłów na optymalizację!

Tal Liron
źródło
3
Ta funkcja kończy się niepowodzeniem na pustym ciągu: isNumber ('') jest prawdą.
Jason Grout
14
function isInteger(x) { return typeof x === "number" && isFinite(x) && Math.floor(x) === x; }
function isFloat(x) { return !!(x % 1); }

// give it a spin

isInteger(1.0);        // true
isFloat(1.0);          // false
isFloat(1.2);          // true
isInteger(1.2);        // false
isFloat(1);            // false
isInteger(1);          // true    
isFloat(2e+2);         // false
isInteger(2e+2);       // true
isFloat('1');          // false
isInteger('1');        // false
isFloat(NaN);          // false
isInteger(NaN);        // false
isFloat(null);         // false
isInteger(null);       // false
isFloat(undefined);    // false
isInteger(undefined);  // false
gówno
źródło
4
Najwyraźniej zmiennoprzecinkowe, które kończą się na .0, są automatycznie rzutowane na Int w JavaScript.
nie udało się z 1.2. Zawsze testuj funkcje numeryczne za pomocą 0,1 0,2 0,3
Lukas Liesis
@LukasLiesis nie jest dla mnie.
doubleOrt
Nie ma tu potrzeby żadnego z operatorów ścisłej równości.
doubleOrt
isFloat (1563457121531) zwraca false
Aalex Gabi
9
function isInt(n) 
{
    return n != "" && !isNaN(n) && Math.round(n) == n;
}
function isFloat(n){
    return n != "" && !isNaN(n) && Math.round(n) != n;
}

działa we wszystkich przypadkach.

Deepak Yadav
źródło
2
+1 To jest dobre. isInt('1')zwraca truezgodnie z oczekiwaniami (przynajmniej dla mnie). Dziwnie mało, chociaż, to powraca truedo isInt([5])jak również. Nie miało to dla mnie znaczenia, ale może dla ciebie, więc uważaj.
acdcjunior
2
isFloat (12.0) jest fałszem
django
6

Jak wspomnieli inni, masz tylko podwójne w JS. Jak więc zdefiniować liczbę będącą liczbą całkowitą? Po prostu sprawdź, czy zaokrąglona liczba jest sobie równa:

function isInteger(f) {
    return typeof(f)==="number" && Math.round(f) == f;
}
function isFloat(f) { return typeof(f)==="number" && !isInteger(f); }
Claudiu
źródło
3
Może chcę sprawdzić, czy wartość jest liczbowa ... isFloat('abc')zwracatrue
Dagg Nabbit
isFloat(NaN) // true
shime
@shime: Good catch. NaN jest technicznie liczbą zmiennoprzecinkową, ale ... zależy od tego, jaki jest przypadek użycia.
Claudiu
6

Co powiesz na ten?

isFloat(num) {
    return typeof num === "number" && !Number.isInteger(num);
}
Goehybrid
źródło
Wypróbuj console.log(isFloat(1.0));wyniki fałszywe.
Fabian Picone
5

Oto, czego używam do liczb całkowitych:

Math.ceil(parseFloat(val)) === val

Krótko, miło :) Działa cały czas. Tak sugeruje David Flanagan, jeśli się nie mylę.

Arman McHitarian
źródło
Podoba mi się ten, ponieważ jest to krótka, prosta odpowiedź, która nie opiera się na tajemniczych operacjach bitowych.
Jim
Dlaczego parseFloat?
doubleOrt
4

To naprawdę zależy od tego, co chcesz osiągnąć. Jeśli chcesz „emulować” silnie napisane języki, sugeruję, abyś nie próbował. Jak wspomniano inni, wszystkie liczby mają tę samą reprezentację (ten sam typ).

Używanie czegoś takiego jak Claudiu zapewniło:

isInteger( 1.0 ) -> prawda

co wygląda dobrze dla zdrowego rozsądku, ale w czymś takim jak C byś dostał false

gblazex
źródło
4

Każda liczba zmiennoprzecinkowa z zerową częścią dziesiętną (np. 1,0, 12,00, 0,0) jest domyślnie rzutowana na liczbę całkowitą, więc nie można sprawdzić, czy są zmiennoprzecinkowe, czy nie.

Mike Mancini
źródło
4
!!(24%1) // false
!!(24.2%1) // true
Виктор Дакалов
źródło
!!(24.0%1)jest fałszywe
Rohmer
3

To naprawdę nie musi być takie skomplikowane. Wartość liczbowa odpowiedników parseFloat () i parseInt () liczb całkowitych będzie taka sama. W ten sposób możesz zrobić tak:

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

Następnie

if (isInt(x)) // do work

Umożliwi to również sprawdzanie ciągów, a zatem nie jest ścisłe. Jeśli chcesz rozwiązania typu silnego (aka, nie będzie działać z ciągami znaków):

function is_int(value){ return !isNaN(parseInt(value * 1) }
SpYk3HH
źródło
isInteger (12.0) jest prawdą
django
3
var isInt = function (n) { return n === (n | 0); };

Nie miałem przypadku, w którym to nie zadziałało.

ankr
źródło
hej przepraszam, dlaczego to zwraca false? console.log (isInt (7932938942839482938));
itme
4
Ponieważ to przekracza MaxInt.
ankr
ale możesz ustawić Int maksymalną długość nope? co jeśli nie wiem, zwracana jest długość całkowita?
itsme
1
@ekussberg Tak, ponieważ 2jest liczbą całkowitą i 23jest uważany za drugi argument funkcji. W javascript dziesiętne są zapisywane za pomocą kropki jako separatora - tak powinno być 2.23.
ankr
1
Lub jest to świetna okazja, aby dowiedzieć się o operacjach bitowych. Zyskasz wiele korzyści z tego, idąc naprzód.
ankr
2

TO JEST OSTATECZNY KOD KONTROLI ZARÓWNO WEWNĘTRZNEJ I PŁYWAKOWEJ

function isInt(n) { 
   if(typeof n == 'number' && Math.Round(n) % 1 == 0) {
       return true;
   } else {
       return false;
   }
} 

LUB

function isInt(n) {   
   return typeof n == 'number' && Math.Round(n) % 1 == 0;   
}   
Ken Le
źródło
To testuje tylko na liczbę zmiennoprzecinkową, jeśli n jest liczbą
hacklikecrack
2
function isInteger(n) {
   return ((typeof n==='number')&&(n%1===0));
}

function isFloat(n) {
   return ((typeof n==='number')&&(n%1!==0));
}

function isNumber(n) {
   return (typeof n==='number');
}
Vitim.us
źródło
Liczba całkowita nie jest liczbą zmiennoprzecinkową? Wiadomości dla mnie
Maarten Bodewes
2

To proste jak:

if( n === parseInt(n) ) ...

Wypróbuj to w konsoli:

x=1;
x===parseInt(x); // true
x="1";
x===parseInt(x); // false
x=1.1;
x===parseInt(x); // false, obviously

// BUT!

x=1.0;
x===parseInt(x); // true, because 1.0 is NOT a float!

To dezorientuje wielu ludzi. Ilekroć coś ma wartość .0, nie jest to już liczba zmiennoprzecinkowa. To jest liczba całkowita. Możesz też nazwać to „rzeczą liczbową”, ponieważ nie ma tak ścisłego rozróżnienia, jak wtedy w C. Dobre, stare czasy.

Zasadniczo wszystko, co możesz zrobić, to sprawdzić liczbę całkowitą, akceptując fakt, że 1.000 jest liczbą całkowitą.

Ciekawa uwaga dodatkowa

Był komentarz na temat wielkich liczb. Ogromne liczby oznaczają ŻADNY problem dla tego podejścia; ilekroć parseInt nie jest w stanie obsłużyć liczby (ponieważ jest zbyt duża), zwróci coś innego niż wartość rzeczywista, więc test zwróci FAŁSZ. Jest to dobra rzecz, ponieważ jeśli uważasz coś za „liczbę”, zwykle spodziewasz się, że JS będzie w stanie to obliczyć - więc tak, liczby są ograniczone i parsuje To weźmie to pod uwagę , mówiąc inaczej.

Spróbuj tego:

<script>

var a = 99999999999999999999;
var b = 999999999999999999999; // just one more 9 will kill the show!
var aIsInteger = (a===parseInt(a))?"a is ok":"a fails";
var bIsInteger = (b===parseInt(b))?"b is ok":"b fails";
alert(aIsInteger+"; "+bIsInteger);

</script>

W mojej przeglądarce (IE8) zwraca to „a jest w porządku; b kończy się niepowodzeniem”, co jest właśnie spowodowane dużą liczbą w b. Limit może się różnić, ale wydaje mi się, że 20 cyfr „powinno wystarczyć każdemu”, żeby zacytować klasykę :)

dkellner
źródło
Jest to w porządku, jeśli potrzebujesz tylko sprawdzić liczby całkowite (z matematyki POV), ale jeśli chcesz się upewnić, że faktycznie działają jak liczby całkowite (z komputerowego POV), to będzie niepoprawne dla dużych liczb. Zobacz ten komentarz .
Dagg Nabbit
Mmmmmmm ... Dlaczego tak myślisz? Mam na myśli, że jeśli parseInt zwraca coś i wydaje się być równe samej zmiennej, możesz być pewien, że n naprawdę działa jako liczba całkowita. Odkryłem, że 99999999999999999999 (czyli 20 razy „9”) jest liczbą, a dodanie jeszcze jednego „9” powoduje, że parseInt kończy się niepowodzeniem (zwracanie 1). Może być zależny od przeglądarki; jednak TAK, istnieje limit i NIE, cokolwiek jest wyłączone, limit nie zwróci prawdy dla powyższego czeku.
dkellner
Chodzi mi o to, że operatory bitowe (które traktują liczby jako liczby 32-bitowe) nie dają oczekiwanych wyników na liczbach, których nie można przedstawić jako liczby 32-bitowe, dlatego te liczby nie powinny być identyfikowane jako liczby całkowite. Jest to zgodne ze sposobem działania proponowanego Number.isInteger.
Dagg Nabbit
Coś może być prawdziwą liczbą całkowitą bez zapisywania jednego określonego sposobu. Rozumiem twój punkt widzenia, ale liczby całkowite są liczbami całkowitymi, ponieważ nie mają części ułamkowej i można je dowolnie dodawać / odejmować bez uzyskiwania wyników zmiennoprzecinkowych. Jeśli traktujesz liczby jako pola bitowe, podejrzewasz coś o sposobie ich przechowywania, co - moim zdaniem - jest praktycznie działającym, ale nie w 100% niezawodnym sposobem. Jeśli szukasz „liczby całkowitej przechowywanej w określony sposób”, cóż, nie jestem pewien, czy istnieje test jednowierszowy, którego można bezpiecznie używać na wszystkich platformach.
dkellner
Liczby, które można wyrazić jako liczby 32-bitowe, działają w 100% niezawodnie z operatorami bitowymi. Nie „zakładasz niczego o tym, jak są przechowywane”; liczby są konwertowane na 32-bitowe liczby całkowite dopełniacza big-endian 2, zgodnie ze specyfikacją. Liczby, których nie można przedstawić w tym formacie, nie powinny być uważane za liczby całkowite. Ponownie jest to zgodne z tym, jak Number.isIntegerdziała. Test jednowierszowy jest n === (n | 0)pokazany w innej odpowiedzi.
Dagg Nabbit
2

To rozwiązanie działało dla mnie.

<html>
<body>
  <form method="post" action="#">
    <input type="text" id="number_id"/>
    <input type="submit" value="send"/>
  </form>
  <p id="message"></p>
  <script>
    var flt=document.getElementById("number_id").value;
    if(isNaN(flt)==false && Number.isInteger(flt)==false)
    {
     document.getElementById("message").innerHTML="the number_id is a float ";
    }
   else 
   {
     document.getElementById("message").innerHTML="the number_id is a Integer";
   }
  </script>
</body>
</html>
Abdelraouf GR
źródło
1

W przypadku liczb całkowitych używam tego

function integer_or_null(value) {
    if ((undefined === value) || (null === value)) {
        return null;
    }
    if(value % 1 != 0) {
        return null;
    }
    return value;
}
neoneye
źródło
1

W skrypcie Java wszystkie liczby są takie internally 64 bit floating pointsame, jak podwójne w Javie. W javascript nie ma różnych typów, wszystkie są reprezentowane według typu number. Dlatego nie będziesz w stanie wykonać instanceofczeku. Możesz jednak użyć powyższych rozwiązań, aby dowiedzieć się, czy jest to liczba ułamkowa. projektanci skryptu Java uważali, że jednym typem mogą uniknąć licznych błędów rzutowania.

Punith Raj
źródło
1

Czasami obiekty Number nie pozwalają na bezpośrednie użycie operatora mod (%), jeśli masz do czynienia z tą sprawą, możesz użyć tego rozwiązania.

if(object instanceof Number ){
   if( ((Number) object).doubleValue() % 1 == 0 ){
      //your object is an integer
   }
   else{
      //your object is a double
   }
}
toddsalpen
źródło
1

Próbując tutaj niektórych odpowiedzi, ostatecznie napisałem to rozwiązanie. Działa to również z liczbami w ciągu.

function isInt(number) {
    if(!/^["|']{0,1}[-]{0,1}\d{0,}(\.{0,1}\d+)["|']{0,1}$/.test(number)) return false;
    return !(number - parseInt(number));
}

function isFloat(number) {
    if(!/^["|']{0,1}[-]{0,1}\d{0,}(\.{0,1}\d+)["|']{0,1}$/.test(number)) return false;
    return number - parseInt(number) ? true : false;
}

    var tests = {
        'integer' : 1,
        'float' : 1.1,
        'integerInString' : '5',
        'floatInString' : '5.5',
        'negativeInt' : -345,
        'negativeFloat' : -34.98,
        'negativeIntString' : '-45',
        'negativeFloatString' : '-23.09',
        'notValidFalse' : false,
        'notValidTrue' : true,
        'notValidString' : '45lorem',
        'notValidStringFloat' : '4.5lorem',
        'notValidNan' : NaN,
        'notValidObj' : {},
        'notValidArr' : [1,2],
    };

    function isInt(number) {
        if(!/^["|']{0,1}[-]{0,1}\d{0,}(\.{0,1}\d+)["|']{0,1}$/.test(number)) return false;
        return !(number - parseInt(number));
    }
    
    function isFloat(number) {
        if(!/^["|']{0,1}[-]{0,1}\d{0,}(\.{0,1}\d+)["|']{0,1}$/.test(number)) return false;
        return number - parseInt(number) ? true : false;
    }

    function testFunctions(obj) {
        var keys = Object.keys(obj);
        var values = Object.values(obj);

        values.forEach(function(element, index){
            console.log(`Is ${keys[index]} (${element}) var an integer? ${isInt(element)}`);
            console.log(`Is ${keys[index]} (${element}) var a float? ${isFloat(element)}`);
        });
    }

    testFunctions(tests);

Alejandro Hernandez
źródło
0

To może nie jest tak wydajne jak% answer, co uniemożliwia najpierw konwersję na ciąg, ale jeszcze nie widziałem, żeby ktoś go opublikował, więc oto inna opcja, która powinna działać dobrze:

function isInteger(num) {
    return num.toString().indexOf('.') === -1;
}

źródło
Dobre podejście IMHO
Siergiej Panfilow
Dodałbym, że metoda ES6 zawiera () czyni tę odpowiedź jeszcze prostszą
0

Dla tych ciekawych, używając Benchmark.js przetestowałem najczęściej głosowane odpowiedzi (i jedną opublikowaną dzisiaj) na ten post, oto moje wyniki:

var n = -10.4375892034758293405790;
var suite = new Benchmark.Suite;
suite
    // kennebec
    .add('0', function() {
        return n % 1 == 0;
    })
    // kennebec
    .add('1', function() {
        return typeof n === 'number' && n % 1 == 0;
    })
    // kennebec
    .add('2', function() {
        return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
    })

    // Axle
    .add('3', function() {
        return n.toString().indexOf('.') === -1;
    })

    // Dagg Nabbit
    .add('4', function() {
        return n === +n && n === (n|0);
    })

    // warfares
    .add('5', function() {
        return parseInt(n) === n;
    })

    // Marcio Simao
    .add('6', function() {
        return /^-?[0-9]+$/.test(n.toString());
    })

    // Tal Liron
    .add('7', function() {
        if ((undefined === n) || (null === n)) {
            return false;
        }
        if (typeof n == 'number') {
            return true;
        }
        return !isNaN(n - 0);
    });

// Define logs and Run
suite.on('cycle', function(event) {
    console.log(String(event.target));
}).on('complete', function() {
    console.log('Fastest is ' + this.filter('fastest').pluck('name'));
}).run({ 'async': true });

0 x 12,832,357 ops/sec ±0.65% (90 runs sampled)
1 x 12,916,439 ops/sec ±0.62% (95 runs sampled)
2 x 2,776,583 ops/sec ±0.93% (92 runs sampled)
3 x 10,345,379 ops/sec ±0.49% (97 runs sampled)
4 x 53,766,106 ops/sec ±0.66% (93 runs sampled)
5 x 26,514,109 ops/sec ±2.72% (93 runs sampled)
6 x 10,146,270 ops/sec ±2.54% (90 runs sampled)
7 x 60,353,419 ops/sec ±0.35% (97 runs sampled)

Fastest is 7 Tal Liron
jnthnjns
źródło
0

Oto mój kod. Sprawdza, czy nie jest to pusty ciąg (który w przeciwnym razie przejdzie), a następnie konwertuje go do formatu numerycznego. Teraz, w zależności od tego, czy chcesz, aby „1.1” było równe 1.1, może to być to, czego szukasz.

var isFloat = function(n) {
    n = n.length > 0 ? Number(n) : false;
    return (n === parseFloat(n));
};
var isInteger = function(n) {
    n = n.length > 0 ? Number(n) : false;
    return (n === parseInt(n));
};

var isNumeric = function(n){

   if(isInteger(n) || isFloat(n)){
        return true;
   }
   return false;

};
Michael Ryan Soileau
źródło
0

Podoba mi się ta mała funkcja, która zwróci prawdę zarówno dla liczb całkowitych dodatnich, jak i ujemnych:

function isInt(val) {
    return ["string","number"].indexOf(typeof(val)) > -1 && val !== '' && !isNaN(val+".0");
}

Działa to, ponieważ 1 lub „1” zamienia się na „1.0”, czyli isNaN () zwraca false na (które następnie negujemy i zwracamy), ale 1.0 lub „1.0” staje się „1.0.0”, podczas gdy „string” staje się „string”. 0 ”, z których żadna nie jest liczbą, więc isNaN () zwraca false (i ponownie zostaje zanegowany).

Jeśli chcesz tylko dodatnich liczb całkowitych, jest ten wariant:

function isPositiveInt(val) {
    return ["string","number"].indexOf(typeof(val)) > -1 && val !== '' && !isNaN("0"+val);
}

lub, dla ujemnych liczb całkowitych:

function isNegativeInt(val) {
    return `["string","number"].indexOf(typeof(val)) > -1` && val !== '' && isNaN("0"+val);
}

isPositiveInt () działa poprzez przesunięcie skonkatenowanego ciągu liczbowego przed testowaną wartość. Na przykład isPositiveInt (1) powoduje, że isNaN () ocenia „01”, co oznacza fałsz. Tymczasem, isPositiveInt (-1) powoduje, że isNaN () ocenia „0-1”, co ocenia true. Negujemy wartość zwrotu, a to daje nam to, czego chcemy. isNegativeInt () działa podobnie, ale bez zanegowania zwracanej wartości isNaN ().

Edytować:

Moja oryginalna implementacja zwróciłaby również wartość true dla tablic i pustych ciągów. Ta implementacja nie ma tej wady. Ma również tę zaletę, że zwraca wcześniej, jeśli val nie jest łańcuchem ani liczbą, lub jeśli jest pustym łańcuchem, co przyspiesza w takich przypadkach. Możesz dalej go modyfikować, zastępując dwie pierwsze klauzule

typeof(val) != "number"

jeśli chcesz dopasować tylko liczby literalne (a nie ciągi znaków)

Edytować:

Nie mogę jeszcze dodawać komentarzy, więc dodaję to do mojej odpowiedzi. Benchmark opublikowany przez @Asok jest bardzo pouczający; jednak najszybsza funkcja nie spełnia wymagań, ponieważ zwraca PRAWDA również dla liczb zmiennoprzecinkowych, tablic, boolanów i pustych ciągów.

Utworzyłem następujący zestaw testów, aby przetestować każdą z funkcji, dodając również moją odpowiedź do listy (funkcja 8, która analizuje ciągi, i funkcja 9, która nie):

funcs = [
    function(n) {
        return n % 1 == 0;
    },
    function(n) {
        return typeof n === 'number' && n % 1 == 0;
    },
    function(n) {
        return typeof n === 'number' && parseFloat(n) == parseInt(n, 10) && !isNaN(n);
    },
    function(n) {
        return n.toString().indexOf('.') === -1;
    },
    function(n) {
        return n === +n && n === (n|0);
    },
    function(n) {
        return parseInt(n) === n;
    },
    function(n) {
        return /^-?[0-9]+$/.test(n.toString());
    },
    function(n) {
        if ((undefined === n) || (null === n)) {
            return false;
        }
        if (typeof n == 'number') {
            return true;
        }
        return !isNaN(n - 0);
    },
    function(n) {
        return ["string","number"].indexOf(typeof(n)) > -1 && n !== '' && !isNaN(n+".0");
    }
];
vals = [
    [1,true],
    [-1,true],
    [1.1,false],
    [-1.1,false],
    [[],false],
    [{},false],
    [true,false],
    [false,false],
    [null,false],
    ["",false],
    ["a",false],
    ["1",null],
    ["-1",null],
    ["1.1",null],
    ["-1.1",null]
];

for (var i in funcs) {
    var pass = true;
    console.log("Testing function "+i);
    for (var ii in vals) {
        var n = vals[ii][0];
        var ns;
        if (n === null) {
            ns = n+"";
        } else {
            switch (typeof(n)) {
                case "string":
                    ns = "'" + n + "'";
                    break;
                case "object":
                    ns = Object.prototype.toString.call(n);
                    break;
                default:
                    ns = n;
            }
            ns = "("+typeof(n)+") "+ns;
        }

        var x = vals[ii][1];
        var xs;
        if (x === null) {
            xs = "(ANY)";
        } else {
            switch (typeof(x)) {
                case "string":
                    xs = "'" + n + "'";
                    break;
                case "object":
                    xs = Object.prototype.toString.call(x);
                    break;
                default:
                    xs = x;
            }
            xs = "("+typeof(x)+") "+xs;
        }

        var rms;
        try {
            var r = funcs[i](n);
            var rs;
            if (r === null) {
                rs = r+"";
            } else {
                switch (typeof(r)) {
                    case "string":
                        rs = "'" + r + "'";
                        break;
                    case "object":
                        rs = Object.prototype.toString.call(r);
                        break;
                    default:
                        rs = r;
                }
                rs = "("+typeof(r)+") "+rs;
            }

            var m;
            var ms;
            if (x === null) {
                m = true;
                ms = "N/A";
            } else if (typeof(x) == 'object') {
                m = (xs === rs);
                ms = m;
            } else {
                m = (x === r);
                ms = m;
            }
            if (!m) {
                pass = false;
            }
            rms = "Result: "+rs+", Match: "+ms;
        } catch (e) {
            rms = "Test skipped; function threw exception!"
        }

        console.log("    Value: "+ns+", Expect: "+xs+", "+rms);
    }
    console.log(pass ? "PASS!" : "FAIL!");
}

Przekartczyłem również test porównawczy z funkcją nr 8 dodaną do listy. Nie opublikuję wyniku, ponieważ są nieco zawstydzające (np. Ta funkcja NIE jest szybka) ...

Wyniki (skrócone - usunąłem udane testy, ponieważ dane wyjściowe są dość długie) są następujące:

Testing function 0
Value: (object) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) false, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: null, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
FAIL!

Testing function 1
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 2
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 3
Value: (object) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (object) false, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Object], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: null, Expect: (boolean) false, Test skipped; function threw exception!
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) 'a', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
FAIL!

Testing function 4
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 5
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 6
Value: null, Expect: (boolean) false, Test skipped; function threw exception!
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 7
Value: (number) 1.1, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (number) -1.1, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (object) true, Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Array], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (boolean) [object Object], Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '', Expect: (boolean) false, Result: (boolean) true, Match: false
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) true, Match: N/A
FAIL!

Testing function 8
Value: (string) '1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) true, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Testing function 9
Value: (string) '1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
Value: (string) '-1.1', Expect: (ANY), Result: (boolean) false, Match: N/A
PASS!

Zostawiłem awarie, abyś mógł zobaczyć, gdzie zawodzi każda funkcja, oraz testy (ciąg) „#”, abyś mógł zobaczyć, jak każda funkcja obsługuje wartości całkowite i zmiennoprzecinkowe w ciągach, ponieważ niektóre mogą chcieć je parsować jako liczby, a niektóre może nie.

Spośród 10 przetestowanych funkcji te, które faktycznie spełniają wymagania OP, to [1,3,5,6,8,9]

KeMBro2012
źródło
0

Warunki swobodnej weryfikacji:

if (lnk.value == +lnk.value && lnk.value != (lnk.value | 0)) 

Warunki sprawdzania poprawności liczb całkowitych:

if (lnk.value == +lnk.value && lnk.value == (lnk.value | 0)) 

Mam nadzieję, że to może być pomocne.

Joe Mike
źródło
0
function int(a) {
  return a - a === 0 && a.toString(32).indexOf('.') === -1
}

function float(a) {
  return a - a === 0 && a.toString(32).indexOf('.') !== -1
}

Możesz dodać, typeof a === 'number'jeśli chcesz wykluczyć ciągi.

Mirek Rusin
źródło