Konwersja number #12
Konwersja number
W tym dziale omówimy sobie konwersje na typ number
, a także konwersje do typu number
, a więc wszystko, co dotyczy konwersji wartości liczbowych.
Konwersja do typu number
Funkcja Number()
jest podstawową funkcją do konwersji na typ number
. Możemy tam przekazać każdą wartość, zobaczmy jakie wyniki daje przy przekazaniu wartości prymitywnych:
console.log(Number(true)); // 1
console.log(Number(false)); // 0
console.log(Number(null)); // 0
console.log(Number(undefined)); // NaN
Po konwersji wartości true
i false
otrzymujemy kolejno wartość 1
i wartość 0
. Wiemy to już z działu o konwersji typów boolean
.
Wartość null
konwertowana jest do wartości 0
. Natomiast wartość undefined
jest konwertowana do wartości NaN
. Tak po prostu wynika ze specyfikacji ECMAScript.
Zdecydowanie więcej możliwości jest, gdy będziemy konwertować liczby zapisane jako string
.
Number()
Pierwszym sposobem konwersji liczb zapisanych jako string jest użycie funkcji Number()
:
console.log(Number('42')); // 42
console.log(Number('42.5')); // 42.5
console.log(Number('42,5')); // NaN
console.log(Number('42xyz')); // NaN
console.log(Number('xyz42')); // NaN
Przy konwersji za pomocą Number()
otrzymujemy tylko dwie poprawne wartości. Liczba całkowita 42
nie jest tutaj żadnym problemem, tak samo liczba dziesiętna 42.5
. Jest poprawna, ponieważ jest zapisana z kropką .
, a nie z przecinkiem ,
.
Wniosek jest z tego taki, że funkcja Number()
dokonuje konwersji z typu string
na typ number
wtedy i tylko wtedy gdy wartości zapisane w typie string
naprawdę prezentują liczbę. Użyjemy więc funkcji Number()
tylko wtedy gdy mamy pewność, że prezentowane wartości typu string
dokładnie
reprezentują wartości liczbowe. Musi więc być zachowany poprawny format i nie może być żadnych innych znaków.
Oczywiście możemy też konwertować stringi, które reprezentują inne formaty liczb:
console.log(Number('0o52')); // 42
console.log(Number('0x2A')); // 42
console.log(Number('0b00101010')); // 42
console.log(Number('1e42')); // 1e+42
W tym przypadku za pomocą funkcji Number()
kolejno konwertujemy liczbę szesnastkową, ósemkową, binarną oraz zapisaną wykładniczo.
parseInt()
Do konwersji możemy też użyć globalnej funkcji parseInt
:
console.log(parseInt('42')); // 42
console.log(parseInt('42.5')); // 42
console.log(parseInt('42,5')); // 42
console.log(parseInt('42xyz')); // 42
console.log(parseInt('xyz42')); // NaN
Widzimy, że funkcja parseInt
oprócz wartości 'xyz42'
zdołała przekonwertować wszystko do typu number
. W tej sytuacji funkcja parseInt
analizuje każdy znak od lewej do prawej. Jeżeli napotka znak, który nie może zostać przekształcony na liczbę, kończy konwersję i zwraca to, co udało jej się
skonwertować.
Dlatego udało się przekonwertować wartość 42xyz
do liczby 42
, ale konwersja wartości xyz42
od razu się kończy po wykryciu pierwszego znaku, który nie jest liczbą i zwracana jest wartość NaN
.
Funkcja parseInt
konwertuje tylko do liczb całkowitych, dlatego nie widzimy w wynikach części ułamkowych. Również możemy przekazać jej tylko wartość string
. Przekazywanie do tej funkcji innych wartości skończy się niespodziewanymi wynikami.
parseInt() z parametrem
Dodatkowo metoda parseInt
przyjmuje jeszcze jeden parametr, który określa podstawę do konwersji. Domyślnym parametrem jest 10
czyli system dziesiętny. Nie musimy tego parametru przekazywać. Zwrócę jednak uwagę, że jeszcze przed ECMAScript 5, wskazanie bazy liczbowej było obowiązkowe.
Możemy zatem za pomocą parseInt
konwertować liczby z systemu szesnastkowego, ósemkowego i dwójkowego:
console.log(parseInt('42', 10)); // 42
console.log(parseInt('2A', 16)); // 42
console.log(parseInt('52', 8)); // 42
console.log(parseInt('00101010', 2)); // 42
Widzimy przykłady przekonwertowanych liczb z różnych systemów z określeniem dodatkowego parametru, którym jest baza liczby.
parseFloat()
Kolejną funkcją, do której możemy przekazać jedynie wartość string
jest funkcja parseFloat
. Działa bardzo podobnie, oprócz tego, że przekonwertuje liczby zapisane w postaci całkowitej, to także przekonwertuje liczby zapisane w postaci dziesiętnej:
console.log(parseFloat('42')); // 42
console.log(parseFloat('42.5')); // 42.5
console.log(parseFloat('42,5')); // 42
console.log(parseFloat('42xyz')); // 42
console.log(parseFloat('xyz42')); // NaN
W tym przypadku udaje nam się przekonwertować stringa '42.5'
do liczby 42.5
. Natomiast nie udaje się przekonwertować '42,5'
do liczby dziesiętnej. Jest to oczywiście prawidłowe zachowanie. Znak przecinka nie zostaje rozpoznany jako składowa liczby, dlatego konwersja kończy się przed
przecinkiem.
Oznacza to, że liczby zawsze muszą być zapisane z kropką, nawet w typie string
, inaczej nie uda nam ich prawidłowo przekonwertować.
Metody do konwersji liczb zapisanych w typie string
działają bardzo dobrze, dopóki nie zaczniemy przekazywać tam innych typów. Upewnijmy się więc, że pracujemy z typem string
, który w jakiś sposób reprezentuje liczbę.
Jeśli pytacie, którą metodę najlepiej użyć do konwersji wszystko zależy od kontekstu. Jeżeli zależy nam na wartościach tylko liczbowych to używamy funkcji Number
i będzie to Wasze najczęstsze użycie. Jeśli natomiast interesują nas liczby zapisane w różny dziwny sposób możecie użyć parseInt
lub parseFloat
.
W typie Number
istnieje także metoda statyczna parseInt
i parseFloat
, którą możemy wywołać przez Number.parseInt
i Number.parseFloat
:
console.log(Number.parseInt('42')); // 42
console.log(Number.parseFloat('42.5')); // 42.5
Działają one dokładnie tak samo, jak omówione metody parseInt
i parseFloat
.
Jak poradzić sobie z liczbami z przecinkiem
Na pewno wielokrotnie będziecie mierzyć się z liczbą zapisaną jako string
z przecinkiem. Niestety nie możemy jej poprawnie konwertować za pomocą wymienionych metod. Bardzo często użytkownicy wpisują liczby w taki sposób i musimy nauczyć się jak je konwertować:
Najlepszym sposobem jest zamiana przecinka na kropkę:
const value = '42,5';
const value2 = value.replace(',', '.');
console.log(parseFloat(value2)); // 42
Możemy użyć funkcji replace
i zamienić przecinek na kropkę. Funkcja ta jest bezpieczna. Jeżeli wartość string
nie będzie posiadała przecinka, nic się nie wydarzy. Po tej zamianie możemy przekonwertować stringa na prawidłową wartość liczbową.
Konwersja przez operator +
oraz -
Innym sposobem na zastąpienie funkcji Number()
jest użycie jedno argumentowanego operatora +
.
Zobaczmy, jak to wygląda w kodzie:
console.log(+null); // 0
console.log(+true); // 1
console.log(+false); // 0
console.log(+'42'); // 42
console.log(+'42.5'); // 42.5
console.log(+'42xyz'); // NaN
console.log(+'foo'); // NaN
Działa on tak samo, jak funkcja Number()
, wyniki konwersji są oczywiście te same. Należy jednak pamiętać, że jest to operator jednoargumentowy. Jeżeli dołożymy drugi argument, to dokonamy działania matematycznego lub konkatenacji.
Wystarczy przed wartością, którą chcemy przekonwertować, postawić znak plus:
const a1 = +'42';
console.log(a1); // 42
Jeżeli jednak chcemy dokonać konwersji i jeszcze potem wykonać jakieś działanie na przykład dodawanie:
const a2 = 2 + +'40';
console.log(a2); // 42
wtedy wyrażenie to możemy zapisać tak, że znaki +
rozdzielamy spacją. Najpierw nastąpi konwersja stringa '40'
do liczby, a potem nastąpi suma dwóch liczb i otrzymamy wynik 42
oczywiście w postaci typu number
. Takie zapisy nie do końca są czytelne i być może lepiej do konwersji użyć
funkcji Number()
co zapewni czytelność tego wyrażenia.
Również istnieje operator jednoargumentowy ze znakiem -
:
console.log(-null); // -0
console.log(-true); // -1
console.log(-false); // -0
console.log(-'42'); // -42
console.log(-'42.5'); // -42.5
console.log(-'42xyz'); // NaN
console.log(-'foo'); // NaN
W tym przypadku jeżeli to możliwe następuje konwersja na typ number
i odwrócenie znaku liczby. Jeżeli zatem chcemy przekonwertować jakaś wartość od razu do liczby ujemnej, jest to bardzo wygodny zapis.
Zasada tych operatorów jest bardzo prosta, a skrócony zapis preferuje wielu developerów. Co ciekawe, jednoargumentowe operatory są najszybsze w swoim działaniu. Jeżeli zależy Wam na wydajności, jest to najlepszy sposób na konwersję do typu number
.
Konwersja przez inne operatory arytmetyczne
Działania arytmetyczne jak dodawanie, odejmowanie i mnożenie w języku JavaScript, realizowane są tylko na liczbach. Dlatego wykonując takie działanie również możemy od razu dokonać konwersji na typ number
:
console.log(true + 0) // 1
console.log(null + 0) // 0
console.log('43' - 1) // 42
console.log('42' * 1) // 42
console.log('84' / 2) // 42
Jak się domyślamy, najpierw dokonywana jest konwersja na typ number
, a potem odpowiednie działanie matematyczne.
Jeżeli chcemy dokonać tylko konwersji, musimy zastosować takie działanie, które nie zmieni nam wyniku. Nic jednak nie stoi na przeszkodzie, aby od razu dokonać działania matematycznego a przy tym konwertując wszystko do typu number
. W ostatnim przykładzie dokonuję dzielenia na literale stringowym
i otrzymuję wynik w postaci liczby.
Musimy oczywiście uważać z operatorem +
jeżeli przy operatorze plus znajdzie się typ string
:
console.log('foo' + 1) // 'foo1'
To w tym przypadku nastąpi konwersja do typu string i połączenie dwóch stringów.
Number na string
Jeśli chodzi o konwersje number
na string to możemy wywołać metodę toString()
lub też posłużyć się funkcją String()
:
const val = 42;
console.log(val.toString()); // '42'
console.log(String(value)); // '42'
Wywoływanie funkcji toString()
może się nie udać, gdy natrafimy na wartość null
lub undefined
. Wtedy JavaScript zgłosi nam błąd. Dlatego bezpiecznie jest zawsze użycie funkcji String()
, do której możemy przekazać każdą wartość.
Inne wartości liczbowe jak NaN
, Infinity
czy -Infinity
też konwertowane są na string
:
console.log(String(NaN)); // 'NaN'
console.log(String(-Infinity)); // '-Infity'
console.log(String(Infinity)); // 'Infity'
Można powiedzieć, że następuje dosłowna konwersja i wartości te zmieniają się na literał typu string.
Bardzo duże liczby po konwersji do typu string
będą zaprezentowane w sposób wykładniczy:
console.log(String(Number.MAX_VALUE)); // '1.7976931348623157e+308'
console.log(String(Number.MAX_VALUE * -1)); // '-1.7976931348623157e+308'
Jeżeli bardzo zależy Wam na zwróceniu tej liczby w normalnej notacji, możecie użyć metody toLocaleString()
:
console.log(Number.MAX_VALUE.toLocaleString());
Metoda ta zwraca stringi dostosowane do lokalizacji. Posiada ona dodatkowe parametry i warto przejrzeć dokumentację, aby w pełni się z nią zapoznać.
Metoda toString()
wywołana na typie number
ma jeszcze jedną dodatkową właściwość:
const num = 42;
console.log(num.toString(2)); // 101010
console.log(num.toString(8)); // 52
console.log(num.toString(16)); // 2a
console.log(num.toString(36)); // 1a
Możemy do metody toString
jako parametr przekazać radix, czyli podstawę systemu liczbowego. W JavaScript możemy konwertować liczby aż do trzydziesto szóstkowego systemu liczbowego. Do metody toString()
wystarczy przekazać odpowiednią liczbę, która będzie reprezentować system liczbowy.
Ponadto oprócz metod toString()
i funkcji String()
mamy metody toExponential()
, toPrecision()
, toFixed()
, które także zwracają liczby w postaci stringa:
const num2 = 42.1234
console.log(num2.toExponential()); // 4.21234e+1
console.log(num2.toFixed(2)); // 42.12
console.log(num2.toPrecision(2)); // 42
Bardziej służą one jednak do formatowania liczb niż tylko do konwersji na typ string. Należy pamiętać, że wiele metod, które wywołujemy na typie number
zwraca nam już typ string
a nie typ number
. Jeżeli nadal potrzebujemy dokonywać działań na typie number
znowu musimy dokonać konwersji na
typ number
.
Number na boolean
Przy konwersji number
na boolean
, sprawa wydaje się prosta i była już omawiana przy typie boolean
:
console.log(Boolean(0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean(NaN)); // false
Otrzymamy wartość false
gdy dokonamy konwersji wartości takich jak 0
, -0
oraz wartość NaN
. Wszystkie pozostałe liczby będą wartościami true
:
console.log(Boolean(1)); // true
console.log(Boolean(-1)); // true
console.log(Boolean(100)); // true
console.log(Boolean(834838)); // true
Zazwyczaj uważa się, że tylko liczba 1
to wartość true
po konwersji do boolean
. Jak wiemy z tabelki wartości fałszywych, tylko wartość 0
, -0
oraz NaN
konwertuje się do typu false
, wszystkie inne liczby konwertują się na true
.
console.log(Boolean(Infinity)); // true
console.log(Boolean(-Infinity)); // true
Nawet tak dziwne wartości number
jak Infinity
oraz -Inifinity
zwrócą nam wartość true
.
Co warto zapamiętać
- funkcja
Number()
może przekonwertować nam każdą wartość do typunumber
- do funkcji
parseInt()
lubparseFloat()
możemy przekazać tylko typstring
- do
parseInt()
możemy przekazać dodatkowy parametr, którym jest baza liczby - do konwersji na
number
możemy użyć jednoargumentowych operatorów+
oraz-
- operacje arytmetyczne także dokonują niejawnej konwersji na typ
number
, należy jednak uważać ze znakiem+
i konkatenacją stringów - konwertując
number
nastring
używamy funkcjiString()
lub metodytoString()
- metody dla typu
number
które służą do formatowania liczb jaktoFixed()
zwracają typstring
- tylko liczby
-0, 0 oraz NaN
konwertują się nafalse
, reszta liczb zawsze konwertuje się natrue
w tymInfinity