CodeGym /Kursy /Frontend SELF PL /Praca z liczbami zmiennoprzecinkowymi

Praca z liczbami zmiennoprzecinkowymi

Frontend SELF PL
Poziom 37 , Lekcja 0
Dostępny

1.1 Zaokrąglanie liczb zmiennoprzecinkowych

Liczby zmiennoprzecinkowe po angielsku nazywane są floating point number – liczby z przecinkiem: w USA do oddzielenia części całkowitej od ułamkowej używa się kropki. Stąd nazwa float.

Jak już omówiliśmy, przy konwersji liczby zmiennoprzecinkowej (float) na całą (int), zawsze jest zaokrąglana w dół do całkowitej — część ułamkowa po prostu jest odrzucana. A przecież łatwo sobie wyobrazić sytuację, gdy liczba ułamkowa musi być zaokrąglona po prostu do najbliższego całkowitego lub nawet w górę. Co wtedy zrobić?

Na taką sytuację w JavaScript mamy wbudowaną funkcję round(). Została stworzona jeszcze przed powstaniem biblioteki Math, dlatego nie wchodzi w jej skład. Funkcje do zaokrąglania w dół i w górę znajdują się w bibliotece math.

Funkcja Math.round()

Funkcja Math.round() zaokrągla liczbę do najbliższej całkowitej:

    
      Math.round(liczba_zmiennoprzecinkowa)
    
  

Ta funkcja zwróci liczbę całkowitą, do której bliżej jest przekazana liczba zmiennoprzecinkowa.

Przykłady:

Komenda Wynik
let x = Math.round(4.1); 4
let x = Math.round(4.5); 5
let x = Math.round(4.9); 5

Funkcja Math.ceil()

Funkcja Math.ceil() zaokrągla liczbę do najbliższej całkowitej w górę:

Komenda Wynik
let x = Math.ceil(4.1); 5
let x = Math.ceil(4.5); 5
let x = Math.ceil(4.9); 5

Funkcja Math.floor()

Funkcja Math.floor() zaokrągla liczbę do najbliższej całkowitej w dół:

Komenda Wynik
let x = Math.floor(4.1); 4
let x = Math.floor(4.5); 4
let x = Math.floor(4.9); 4

Jeśli trudno ci zapamiętać te komendy, pomoże ci mała lekcja angielskiego:

  • math — matematyka
  • round — okrąg/zaokrąglać
  • ceiling — sufit
  • floor — podłoga

1.2 Struktura liczb zmiennoprzecinkowych

Typ number w JavaScript może przechowywać wartości w zakresie od -1.7*10308 do +1.7*10308. Takie ogromne wartości wynikają z faktu, że typ number jest zbudowany całkowicie inaczej w porównaniu z typami całkowitymi. Każda zmienna typu number zawiera dwie liczby: pierwsza nazywa się mantysa, a druga — wykładnik.

Załóżmy, że mamy liczbę 123456789, i zapisaliśmy ją w zmiennej typu number. Wówczas liczba zostanie przekształcona do postaci 1.23456789*108, a wewnątrz typu number będą przechowywane liczby — 1.23456789 i 8. Na czerwono zaznaczono „znaczącą część liczby” (mantysę), na niebiesko — wykładnik.

Takie podejście pozwala przechowywać zarówno bardzo duże liczby, jak i bardzo małe. Ale ponieważ rozmiar liczby jest ograniczony do 8 bajtów (64 bitów) i część bitów jest wykorzystywana na przechowywanie wykładnika (a także znaku liczby i znaku wykładnika), maksymalna długość mantysy jest ograniczona do 15 cyfr.

To bardzo uproszczony opis struktury liczb zmiennoprzecinkowych: bardziej szczegółowe można znaleźć pod tym linkiem.

1.3 Utrata dokładności przy pracy z liczbami zmiennoprzecinkowymi

Pracując z liczbami zmiennoprzecinkowymi, zawsze musisz mieć na uwadze, że liczby zmiennoprzecinkowe są niedokładne. Zawsze będą błędy zaokrąglenia, błędy konwersji z systemu dziesiętnego na binarny, i wreszcie najczęstsze — utrata dokładności przy dodawaniu/odejmowaniu liczb o bardzo różnej skali.

Ostatnie to najbardziej zaskakująca sytuacja dla początkujących w programowaniu.

Jeśli odejmujesz od liczby 109 1/109, dostaniesz z powrotem 109.

Odejmowanie liczb o bardzo różnej skali Wyjaśnienie
1000000000.000000000
-      0.000000001
1000000000.000000000
Druga liczba jest zbyt mała i jej znacząca część jest pomijana (zaznaczono na szaro). Na czerwono zaznaczono 15 znaczących cyfr.

Co tu dużo mówić, programowanie to nie matematyka.

1.4 Niebezpieczeństwo porównywania liczb zmiennoprzecinkowych

Kolejne niebezpieczeństwo czyha na programistów przy porównywaniu liczb zmiennoprzecinkowych. Ponieważ przy pracy z tymi liczbami mogą się gromadzić błędy zaokrąglenia, mogą wystąpić sytuacje, gdy liczby zmiennoprzecinkowe powinny być równe, ale nie są. I odwrotnie: liczby powinny być różne, a są równe.

Przykład:

Komenda Wyjaśnienie
let a = 1000000000.0
let b = 0.000000001
let c = a – b
W zmiennej a będzie wartość 1000000000.0.
W zmiennej c będzie wartość 1000000000.0
(liczba w zmiennej b jest zbyt mała).

W powyższym przykładzie a i c nie powinny być równe, ale są.

Albo inny przykład:

Komenda Wyjaśnienie
let a = 1.00000000000000001
let b = 1.00000000000000002
W zmiennej a będzie wartość 1.0.
W zmiennej b będzie wartość 1.0.

W praktyce liczby zmiennoprzecinkowe porównuje się tak:

Jeśli różnica liczb (moduł) jest mniejsza niż jakaś bardzo mała liczba, są one uważane za równe.

Przykład:

JavaScript
    
      let a = 0.00000000012;
      let b = 0.000000000011;

      if (Math.abs(a - b) < 0.00001) {
        console.log("równy");
      } else {
        console.log("nie równy");
      }
    
  
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION