Number - czyli typ danych pozwalający pracować na liczbach.
W większości przypadków będziemy zapisywać liczby normalnie - tak jak się przyzwyczailiśmy:
const nr1 = 102;
const nr2 = 1.25;
Jeżeli chcemy zapisać liczbę z większą liczbą zer, możemy to zrobić normalnie powtarzając kolejne zera, ale też możemy zastosować zapis z literą e, po której podajemy liczbę zer. Dzięki temu ciężej zrobić błąd:
const nr1 = 1e6; //1 * 1000000
const nr2 = 2e5; //2 * 100000
const nr3 = 1.3e4; //1.3 * 10000
Podobną techniką możemy zapisywać liczby bardzo małe:
const nr1 = 1e-5; //5 zer na lewo od liczby => 0.00001
const nr2 = 2e-3; //3 zera na lewo 0.002
const nr3 = 2.1e-4; //4 zera na lewo 0.00021
Kolejnym sposobem zapisu liczb jest system dwójkowy, hexadecymalny oraz ósemkowy. Nie są to zapisy często używane, ale w skrajnych sytuacjach może się pojawić:
//szesnastkowy - znany z kolorów CSS
document.write( 0xFF ); //255
document.write( 0x66 ); //102
//ósemkowy
const nr1 = 0o377; //255
//dwójkowy
const nr2 = 0b11111111; //255
document.write( 0xFF === 0o377 === 0b11111111); //true
Każdy (prawie) typ danych w Javascript może korzystać z funkcji toString()
,
która zamienia go na zapis tekstowy.
W przypadku typu Number, metoda ta pozwala podać w nawiasach podstawę/system (z zakresu 1-36),
która zostanie użyta do reprezentacji danej liczby:
const nr = 150;
document.write(nr.toString(16)); //"96"
document.write(nr.toString(10)); //"150"
document.write(nr.toString(2)); //"10010110"
document.write(nr.toString()); //"150" - domyślnie dziesiętny
Rozważmy proste równanie:
document.write( 0.1 + 0.2 ); //0.30000000000000004
Z czego wynika tak dziwny wynik?
Komputery to twory, które przechowują dane w formie bitów, czyli zapisie zer i jedynek (tak zwany system dwójkowy).
Część liczb niestety nie jest możliwa do przedstawienia w tym systemie.
Można to przyrównać do używanego na co dzień systemu dziesiętnego.
Przykładowo ułamek ½ możemy w systemie dziesiętnym zapisać jako 0.5. Podobnie ułamek ¼ zapiszemy jako 0.25.
Gdybyśmy podobnie chcieli zapisać ułamek ⅓, okazało by się, że nie jesteśmy tego w 100% zrobić, ponieważ nigdy nie osiągniemy pełnej precyzji 0.33333...
Podobnie w systemie dwójkowym niektórych liczb nie jesteśmy w stanie zapisać.
Problem ten tyczy się wszystkich obecnych komputerów i spotykany jest w wielu językach (np. Perl. C++, Java, PHP) ale też i w grach.
W przypadku Javascript do zapisu liczb w pamięci wykorzystywany jest używany powszechnie standard, który charakteryzuje się tym, że przy operacjach na liczbach o bardzo małej precyzji, zaokrąglane są one do najbliższej możliwej do zapisu w systemie dwójkowym liczby.
document.write( 0.1.toFixed(20) ); // 0.10000000000000000555
document.write( 9999999999999999 ); //10000000000000000 - podobna rzecz, ale w drugą stronę
W 99.99% przypadków nie będzie to miało dla nas znaczenia i prawdopodobnie przy normalnej pracy nigdy się z nim nie zetkniesz.
Jeżeli jednak kiedyś na swojej drodze spotkasz się z zadaniem zrobienia sklepu,
który operuje na bilionach krypto monet, pewnie będziesz musiał skorzystać ze specjalnych algorytmów,
które służą do redukcji takich "przesunięć".
Na co dzień jednak nie ma co się tym przejmować.
JavaScript udostępnia nam obiekt Math, który ułatwia nam przeprowadzanie operacji matematycznych.
Metody
Math.abs(liczba) | - zwraca wartość bezwzględną liczby |
Math.ceil(liczba) | - zwraca najmniejszą liczbę całkowitą, większą lub równą podanej liczbie |
Math.floor(liczba) | - zwraca największą liczbę całkowitą mniejszą lub równą podanej liczbie |
Math.max(liczba1, liczba2, liczba3...) | - zwraca największą przekazaną liczbę |
Math.min(liczba1, liczba2, liczba3...) | - zwraca najmniejszą przekazaną liczbę |
Math.pow(liczba1, liczba2) | - zwraca wartość liczby1 podniesionej do potęgi liczby2 |
Math.random() | - zwraca wartość pseudolosową z przedziału 0 - 1 |
Math.round(liczba) | - zwraca zaokrąglenie danej liczby do najbliższej liczby całkowitej |
Math.sin(liczba) | - zwraca sinus liczby (podanej w radianach) |
Math.sqrt(liczba) | - zwraca pierwiastek kwadratowy liczby |
Kilka przykładów zastosowania Obiektu Math:
const var1 = 56.5;
const var2 = 74.3;
Math.min(var1, var2) //56.5
Math.max(var1, var2)) //74.3
Math.max(1,3,6,2) //6
Math.abs(-1) //1
Math.round(var1) //56
Math.round(20.52) //21
Math.round(-10.21) //-10
Math.round(-11.82) //-12
Math.floor(var1) //56
Math.floor(20.52) //20
Math.floor(-10.21) //-11
Math.floor(-11.82) //-12
Math.ceil(var1) //57
Math.ceil(20.52) //21
Math.ceil(-10.21) //-10
Math.ceil(-11.82) //-11
Aby wygenerować liczbę losową z przedziału np. 3-7 skorzystaj z poniższego wzoru:
const min = 3;
const max = 7;
const result = Math.floor(Math.random() * (max-min+1) + min);
Wzór podpatrzony w internecie, ale ciekawie pokazuje zastosowanie powyższych informacji. Aby wygenerować losowy kolor możemy skorzystać z wielu sposobów.
function randomColor() {
const letters = "0123456789ABCDEF";
let color = "#";
for (let i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
document.write( randomColor() );
document.write( randomColor() );
document.write( randomColor() );
Inna ciekawa sztuczka:
const color = "#" + Math.random().toString(16).substr(2,6);
/*
Powyższe równanie możemy rozpisać na kroki:
1)
Math.random() - zwraca liczbę z przedziału 0-1
0.0264363764209139
2)
Number.toString(16) - zapisuje liczbę w danym systemie jako string
0.0264363764209139.toString(16) da nam "0.06c488cc270ee"
3)
"0.06c488cc270ee".subStr(2,6) - wycinamy litery od 3 do 7
czyli w wyniku uzyskamy "06c488"
4)
Dodajemy # i mamy kolor
"#" + "06c488" === "#06c488"
*/
Powyższe sztuczki generują kolory niezbyt żywe.
Aby generować bardziej żywe kolory wystarczy skorzystać z innego formatu czyli hsl:
function randomColor() {
const deg = Math.random() * 360;
return `hsl(${deg}, 60%, 50%)`;
}
const color = randomColor();