Jaki jest najczystszy i najskuteczniejszy sposób sprawdzania poprawności liczb dziesiętnych w JavaScript?
Punkty bonusowe za:
- Przejrzystość. Rozwiązanie powinno być czyste i proste.
- Międzyplatformowy.
Przypadki testowe:
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
javascript
validation
numbers
Michael Haren
źródło
źródło
jQuery.isNumeric
narzędzia: api.jquery.com/jQuery.isNumericjQuery.isNumeric
zakończy się niepowodzeniem siódmego przypadku testowego OP (IsNumeric('0x89f') => *false*
). Nie jestem jednak pewien, czy zgadzam się z tym przypadkiem testowym.Odpowiedzi:
Odpowiedź Joela jest dość bliska, ale nie powiedzie się w następujących przypadkach:
Jakiś czas temu musiałem zaimplementować
IsNumeric
funkcję, aby dowiedzieć się, czy zmienna zawiera wartość liczbową, niezależnie od jej typu , może to być wartośćString
zawierająca wartość liczbową (musiałem rozważyć także notację wykładniczą itp.),Number
Obiekt, praktycznie wszystko może być przekazane do tej funkcji, nie mogłem przyjmować żadnych założeń typu, dbając o przymus typu (np.+true == 1;
aletrue
nie należy tego uważać za"numeric"
).Myślę, że warto udostępnić ten zestaw testów jednostkowych +30 wykonanych dla wielu implementacji funkcji, a także udostępnić ten, który przejdzie wszystkie moje testy:
PS isNaN i isFinite mają mylące zachowanie z powodu wymuszonej konwersji na liczbę. W ES6 Number.isNaN i Number.isFinite rozwiązałyby te problemy. Pamiętaj o tym podczas ich używania.
Aktualizacja : Oto jak robi to teraz jQuery (stabilny w wersji 2.2) :
Aktualizacja : Angular 4.3 :
źródło
2e308 > Number.MAX_VALUE
ponieważ2e308 == Infinity
. Jeśli chcesz funkcji, która zwracatrue
również dodatnie i ujemne wartości nieskończoności, sprawdź funkcję nr 2 w zestawie testów . Twoje zdrowie.Arrrgh! Nie słuchaj odpowiedzi na wyrażenia regularne. RegEx jest do tego obrzydliwy i nie mówię tylko o wydajności. Łatwo jest zrobić subtelne, niemożliwe do wykrycia błędy za pomocą wyrażenia regularnego.
Jeśli nie możesz użyć
isNaN()
, powinno to działać znacznie lepiej:Oto jak to działa:
(input - 0)
Wyrażenie zmusza JavaScript robić typu przymus na wartość wejściowa; należy go najpierw interpretować jako liczbę dla operacji odejmowania. Jeśli konwersja na liczbę nie powiedzie się, wyrażenie zakończy się wynikiemNaN
. Ten wynik liczbowy jest następnie porównywany z oryginalną wartością, którą podałeś. Ponieważ lewa strona jest teraz numeryczna, ponownie stosuje się wymuszenie typu. Teraz, gdy dane wejściowe z obu stron zostały wymuszone na ten sam typ z tej samej pierwotnej wartości, można by pomyśleć, że powinny zawsze być takie same (zawsze prawdziwe). Istnieje jednak specjalna reguła, która mówi, żeNaN
nigdy nie jest równaNaN
, a więc wartość, której nie można przekonwertować na liczbę (i tylko wartości, których nie można przekonwertować na liczby), spowoduje fałsz.Kontrola długości dotyczy specjalnego przypadku z pustymi łańcuchami. Zauważ też, że spada on w teście 0x89f, ale to dlatego, że w wielu środowiskach jest to dobry sposób na zdefiniowanie literału liczbowego. Jeśli chcesz uchwycić ten konkretny scenariusz, możesz dodać dodatkową kontrolę. Co więcej, jeśli to jest powód, dla którego nie używasz,
isNaN()
po prostu obejmij własną funkcję,isNaN()
która może również wykonać dodatkowe sprawdzenie.Podsumowując, jeśli chcesz wiedzieć, czy wartość można przekonwertować na liczbę, faktycznie spróbuj przekonwertować ją na liczbę.
Wróciłem i zbadałem, dlaczego łańcuch białych znaków nie ma oczekiwanego wyniku i myślę, że teraz go rozumiem:
0
zamiast tego jest wymuszany pusty ciągNaN
. Po prostu przycięcie sznurka przed sprawdzeniem długości poradzi sobie z tym przypadkiem.Uruchamianie testów jednostkowych dla nowego kodu i kończy się niepowodzeniem tylko w przypadku literałów nieskończoności i logicznej, a jedynym problemem, który powinien stanowić problem, jest wygenerowanie kodu (naprawdę, kto napisałby literał i sprawdził, czy jest to wartość liczbowa? Powinieneś wiedzieć ), a byłby to jakiś dziwny kod do wygenerowania.
Ale znowu jedynym powodem, aby tego użyć, jest to, że z jakiegoś powodu musisz unikać toNaN ().
źródło
IsNumeric(' ')
,IsNumeric('\n\t')
itd wszystkim powróttrue
Number
literachIsNumeric(5) == false;
sprawdź zestaw testów jednostkowych, które opublikowałem, ta funkcja jest liczbą16
w zestawie testów. stackoverflow.com/questions/18082/...Ten sposób wydaje się działać dobrze:
W jednej linii:
I aby to przetestować:
Pożyczyłem to wyrażenie regularne z http://www.codetoad.com/javascript/isnumeric.asp . Wyjaśnienie:
źródło
Wieśniak! Interfejs użytkownika używa tego:
źródło
new Number(1)
.Działa to również dla liczb typu 0x23.
źródło
IsNumeric('')
,IsNumeric(' ')
,IsNumeric(true)
,IsNumeric(false)
,IsNumeric(null)
Powróttrue
zamiastfalse
.Przyjęta odpowiedź nie zdała testu nr 7 i myślę, że to dlatego, że zmieniłeś zdanie. Jest to więc odpowiedź na zaakceptowaną odpowiedź, z którą miałem problemy.
Podczas niektórych projektów musiałem zweryfikować niektóre dane i mieć jak największą pewność, że jest to wartość liczbowa javascript, której można używać w operacjach matematycznych.
jQuery i niektóre inne biblioteki javascript zawierają już taką funkcję, zwykle wywoływaną
isNumeric
. Istnieje również post dotyczący przepełnienia stosu , który został powszechnie zaakceptowany jako odpowiedź, ta sama ogólna procedura, której używają wspomniane biblioteki.Po pierwsze, powyższy kod zwróciłby wartość true, jeśli argument byłby tablicą o długości 1, a ten pojedynczy element był typu uznanego za numeryczny przez powyższą logikę. Moim zdaniem, jeśli jest to tablica, to nie jest liczbowa.
Aby złagodzić ten problem, dodałem czek, aby zdyskontować tablice z logiki
Oczywiście możesz zamiast tego użyć
Array.isArray
, jquery$.isArray
lub prototypuObject.isArray
Object.prototype.toString.call(n) !== '[object Array]'
Mój drugi problem polegał na tym, że ciągi liczb całkowitych ujemnych liczb szesnastkowych („-0xA” -> -10) nie były liczone jako liczby. Jednak dodatnie szesnastkowe ciągi literału liczby całkowitej („0xA” -> 10) były traktowane jako liczby. Musiałem być poprawnym numerycznie.
Następnie zmodyfikowałem logikę, aby uwzględnić to.
Jeśli martwisz się tworzeniem wyrażenia regularnego za każdym razem, gdy wywoływana jest funkcja, możesz przepisać ją w ramach zamknięcia, coś takiego
Następnie wziąłem CMS +30 przypadków testowych i sklonowałem testy na jsfiddle, dodałem moje dodatkowe przypadki testowe i moje wyżej opisane rozwiązanie.
Może nie zastąpić powszechnie przyjętej / używanej odpowiedzi, ale jeśli jest to więcej, niż oczekujesz, jako wynik funkcji isNumeric, to mam nadzieję, że będzie to pomocne.
EDYCJA: Jak zauważył Bergi , istnieją inne możliwe obiekty, które można by uznać za numeryczne i lepiej byłoby umieścić na białej liście niż na czarnej liście. Mając to na uwadze, dodałbym do kryteriów.
Chcę, aby moja funkcja isNumeric uwzględniała tylko liczby lub ciągi znaków
Mając to na uwadze, lepiej byłoby użyć
Przetestuj rozwiązania
źródło
IsNumeric('99,999') => false
Tak, wbudowany
isNaN(object)
będzie znacznie szybszy niż jakakolwiek analiza wyrażeń regularnych, ponieważ jest wbudowany i skompilowany, a nie interpretowany w locie.Chociaż wyniki różnią się nieco od tego, czego szukasz ( spróbuj ):
źródło
Użyj funkcji
isNaN
. Wierzę, że jeśli przetestujesz!isNaN(yourstringhere)
to działa dobrze w każdej z tych sytuacji.źródło
Od jQuery 1.7 możesz używać
jQuery.isNumeric()
:Pamiętaj tylko, że w przeciwieństwie do tego, co powiedziałeś,
0x89f
jest to poprawna liczba (hexa)źródło
Można to zrobić bez RegExp as
źródło
Zdaję sobie sprawę, że pierwotne pytanie nie wspominało o jQuery, ale jeśli używasz jQuery, możesz:
Prosty.
https://api.jquery.com/jQuery.isNumeric/ (od jQuery 1.7)
źródło
nie działało dla mnie. Kiedy wprowadziłem alert i przetestowałem,
input.length
byłoundefined
. Myślę, że nie ma właściwości do sprawdzania długości całkowitej. Więc to, co zrobiłem, byłoDziała dobrze.
źródło
Jeśli się nie mylę, powinno to być zgodne z dowolną poprawną wartością numeru JavaScript, z wyłączeniem stałych (
Infinity
,NaN
) i operatorów znaków+
/-
(ponieważ, o ile mnie to nie dotyczy, są oddzielnymi operatorami):Potrzebowałem tego dla tokenizera, w którym wysłanie numeru do JavaScript w celu oceny nie było opcją ... To zdecydowanie nie jest najkrótsze możliwe wyrażenie regularne, ale uważam, że przechwytuje wszystkie subtelności składni liczb JavaScript.
Prawidłowe liczby obejmują:
Nieprawidłowe liczby to
źródło
Jedyny problem miałem z @ CMS za odpowiedź jest wyłączenie
NaN
i nieskończoności, które są przydatne numery dla wielu sytuacjach. Jednym ze sposobów, aby sprawdzić, czyNaN
jest to do sprawdzenia wartości liczbowych, które NIE równa samiNaN != NaN
! Tak naprawdę są 3 testy, z którymi chciałbyś się uporać ...Mój isComparableNumber jest dość zbliżony do innej eleganckiej odpowiedzi , ale obsługuje szesnastkowe i inne ciągi znaków liczb.
źródło
Dla mnie to najlepszy sposób:
źródło
Chciałbym dodać następujące:
Dodatnie liczby szesnastkowe zaczynają się od,
0x
a ujemne liczby szesnastkowe zaczynają się od-0x
. Dodatnie liczby ósemkowe zaczynają się od,0
a ujemne liczby ósemkowe zaczynają się od-0
. Ten bierze pod uwagę większość tego, co już wspomniano, ale zawiera liczby szesnastkowe i ósemkowe, ujemny naukowy, Nieskończoność i usunął dziesiętny naukowy (4e3.2
jest nieważny).źródło
Myślę, że funkcja parseFloat może tutaj wykonać całą pracę. Poniższa funkcja przechodzi wszystkie testy na tej stronie, w tym
isNumeric(Infinity) == true
:źródło
IsNumeric([3]) == true;
IsNumeric([]) == false;
IsNumeric([3, 4]) == false;
Ale wyobrażam sobie, że to kwestia gustu!Kilka testów do dodania:
Wymyśliłem to:
Rozwiązanie obejmuje:
źródło
Wartość całkowitą można zweryfikować przez:
W ten sposób jest łatwiej i szybciej! Wszystkie testy są sprawdzane!
źródło
Oto nieco ulepszona wersja (prawdopodobnie najszybsza droga), której używam zamiast dokładnego wariantu jQuery, naprawdę nie wiem, dlaczego tego nie używają:
Wadą wersji jQuery jest to, że jeśli przejdą ciąg z wiodącym numeryczne i końcowe litery jak będzie wyodrębnić część numeryczną i odesłać 123, ale drugi strażnik będzie to nie tak. Dzięki jednemu operatorowi umrze na pierwszym straży, ponieważ + rzuca NaN dla takich hybryd :) Trochę wydajności, ale myślę, że jest to znaczny zysk semantyczny.
"123abc"
parseFloat | parseInt
isFinite
+
źródło
Moje rozwiązanie
Wygląda na to, że działa w każdej sytuacji, ale mogę się mylić.
źródło
?
dla{0,1}
i\d
dla[0-9]
. Ponadto,+
a następnie owijając go(?:){0,1}
, możesz równie dobrze wykorzystać*
i zapomnieć o grupach (nie) przechwytujących.Używam prostszego rozwiązania:
źródło
To powinno działać. Niektóre przedstawione tu funkcje są wadliwe, powinny też być szybsze niż jakakolwiek inna funkcja tutaj.
Wyjaśnione:
Utwórz kopię samego siebie, a następnie konwertuje liczbę na liczbę zmiennoprzecinkową, a następnie porównuje się z liczbą oryginalną, jeśli nadal jest liczbą (całkowitą lub zmiennoprzecinkową) i pasuje do pierwotnej liczby, co oznacza, że rzeczywiście jest liczbą.
Działa zarówno z ciągami liczbowymi, jak i liczbami zwykłymi. Nie działa z liczbami szesnastkowymi.
Ostrzeżenie: używaj na własne ryzyko, bez gwarancji.
źródło
Żadna z odpowiedzi nie zwraca
false
pustych ciągów, to poprawka ...źródło
Aby sprawdzić, czy zmienna zawiera prawidłową liczbę, a nie tylko ciąg znaków, który wygląda jak liczba,
Number.isFinite(value)
Można .Od tego czasu jest to część języka ES2015
Przykłady:
źródło
Number.isFinite('0') -> false
Jeśli n jest liczbowe
Number(n)
, zwróci wartość liczbową itoString()
zwróci ją z powrotem do łańcucha. Ale jeśli n nie jest liczbą,Number(n)
to zwróci,NaN
więc nie będzie pasować do oryginałun
źródło
Zdaję sobie sprawę, że na to pytanie udzielono odpowiedzi wiele razy, ale poniżej znajduje się porządny kandydat, który może być przydatny w niektórych scenariuszach.
należy zauważyć, że zakłada, że „.42” NIE jest liczbą, a „4.” NIE jest liczbą, więc należy to wziąć pod uwagę.
isDecimal
Przechodzi następujący test:Chodzi o to, że każda liczba lub liczba całkowita ma jedną „kanoniczną” reprezentację ciągu, a każda niekanoniczna reprezentacja powinna zostać odrzucona. Rzucamy więc na liczbę i wstecz i sprawdzamy, czy wynikiem jest oryginalny ciąg.
To, czy te funkcje są dla Ciebie przydatne, zależy od przypadku użycia. Jedną z cech jest to, że różne ciągi reprezentują różne liczby (jeśli oba przekazują znak
isNumber()
test).Dotyczy to np. Liczb jako nazw właściwości obiektów.
źródło
knockoutJs Wbuduj funkcje sprawdzania poprawności biblioteki
Po rozszerzeniu pole jest sprawdzane
1) numer
self.number = ko.observable(numberValue)
.extend ({number: true}) ;TestCase
2) cyfra
self.number = ko.observable(numberValue)
.extend ({cyfra: prawda}) ;TestCase
3) min. I maks
self.number = ko.observable(numberValue)
.extend ({min: 5}). ext ({max: 10}) ;To pole przyjmuje wartość tylko od 5 do 10
TestCase
źródło
Jeśli chcesz sprawdzić poprawność specjalnego zestawu miejsc po przecinku, możesz użyć tego prostego javascript:
http://codesheet.org/codesheet/x1kI7hAD
JavaScript:
źródło
isNumeric=(el)=>{return Boolean(parseFloat(el)) && isFinite(el)}
Nic bardzo innego, ale możemy użyć konstruktora boolowskiego
źródło