JavaScript funkcje matematyczne

w tym dziale:

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

Funkcja toString()

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

Niedokładne liczenie

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ć.

Math

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

Losowa liczba z przedziału

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);

Losowy kolor

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();
Projekt i wykonanie: Ryszard Rogacz© 1999−2024