Czym jest Literał Liczbowy?
W programowaniu, literał liczbowy to po prostu sposób przedstawienia liczby w kodzie. Przykładem są liczby takie jak 42
czy 3.14
, które wpisujesz bezpośrednio w swój kod JavaScript. Co ciekawe, w JavaScript nie rozróżniamy typów liczb całkowitych od liczb zmiennoprzecinkowych – obie te formy to po prostu liczby.
Różne Formaty Zapisu Liczb w JavaScript
W JavaScript możemy spotkać się z kilkoma sposobami zapisywania liczb, każdy z nich ma swoje zastosowanie:
Format dziesiętny(Decimal)
Jest to standardowy sposób zapisu liczb, wykorzystujący cyfry od 0 do 9. np :10, 23, 1000
Format szesnastkowy(Hexadecimal)
Wykorzystuje cyfry od 0 do 9 oraz litery od A do F (lub a do f), reprezentujące liczby 10–15. Najczęstszym wykorzystaniem tego formatu w programowaniu JavaScript to zapis kolorów:
let colorRed = 0xFF0000;
Format wykładniczy(Exponential)
Pozwala na zapisanie dużych i małych liczb w sposób bardziej zwięzły. Używa litery e
lub E
, na przykład 4.2e3
, co oznacza 4.2 * 10^3
czyli 4200
Zapis z separatorem
JavaScript umożliwia zapis liczb z separatorem tysięcznym dla lepszej czytelności.
let numberWithSeparator = 1_000_000;
console.log(numberWithSeparator);
// Wyświetli: 1000000
W tym przypadku, _
działa jako separator, pomagając łatwo odczytać, że liczba to milion. Jest to szczególnie przydatne, gdy pracujesz z dużymi liczbami i chcesz zachować klarowność swojego kodu.
Z pomięciem 0
W liczbach zmiennoprzecinkowym 0 w części dziesiętnej jest opcjonalne, tak jak i w części ułamkowej
let floatingPointNumber = .123;
console.log(floatingPointNumber);
// Wyświetli: 0.123
Liczby specjalne
W JavaScript istnieją pewne specjalne wartości liczbowe, które warto znać:
Nieskończoność (Infinity
)
Jeżeli wynik działania arytmetycznego wychodzi po za dopuszczalną wartość, zwraca jest wartość Infinity
czyli nieskończoność. Zakres dopuszczalnych wartości można sprawdzić korzystając z globalnych zmiennych
Number.MAX_VALUE
//1.7976931348623157e+308
Number.MAX_SAFE_INTEGER
//9007199254740991
Number.MIN_VALUE
//5e-324
Number.MIN_SAFE_INTEGER
//-9007199254740991
NaN (Not a Number)
Jest to specjalna wartość reprezentująca „nieliczbę”. Możesz ją spotkać, gdy operacja arytmetyczna nie daje sensownego wyniku, jak w przypadku dzielenia 0/0
czy próby wykonania operacji arytmetycznej na stringu, np. "string"/2
.
0/0
//Wynik NaN
"string"/2
//Wynik NaN
Mimo nazwy, typeof NaN
zwraca 'number'
, więc lepiej myśleć o NaN
jako o błędzie arytmetycznym lub niepoprawnej wartości liczbowej.
typeof("string"/2);
//Wynik: 'number'
BigInt
Dzięki BigInt(dodany w wersji EcmaScript 2020) możesz pracować z liczbami, które są zbyt duże, by być poprawnie przedstawione za pomocą standardowego typu Number
. Aby utworzyć liczbę typu BigInt, wystarczy dodać literę n
na końcu liczby. Oto przykład:
const myBigInt = 123n;
Błędy w zaokrągleniach
Błędy związane z zaokrąglaniem liczb są powszechnie obecne w programowaniu(nie tylko w JavaScript), zwłaszcza przy operacjach na liczbach zmiennoprzecinkowych. Najpopularniejsze przypadki:
let result = 0.1 + 0.2; // 0.30000000000000004
console.log(result === 0.3);
//Wynik: false
let largeNumber = 9999999999999999.99;
let result = largeNumber + 1;
console.log(result);
//Wynik: 10000000000000000
let problematicResult = 0.3 - 0.2; // 0.09999999999999998
console.log(problematicResult === 0.1);
//Wynik: false
Dlaczego tak się dzieje?
Komputery operują na systemie binarnym (bazującym na dwóch stanach, 0 i 1), w przeciwieństwie do codziennego systemu dziesiętnego, którego używamy na co dzień (bazującego na cyfrach od 0 do 9). Ta różnica powoduje, że niektóre liczby dziesiętne nie mają dokładnego odpowiednika w binarnym świecie komputera.
Przykładowo, w systemie dziesiętnym liczba 0.2
to po prostu 0.2
. Ale w systemie binarnym, ta sama liczba staje się nieskończonym ciągiem cyfr: 0.00110011001100110011...
. Podobnie dzieje się z 0.1
, które w binarnym staje się 0.00011001100110011...
.
Komputer nie ma możliwości przechowywania nieskończenie długich ciągów binarnych. Dlatego musi dokonać zaokrąglenia tych wartości do najbliższej możliwej do przechowania liczby, co prowadzi do niewielkich błędów reprezentacji.
Kiedy te zaokrąglone wartości są używane w obliczeniach i następnie konwertowane z powrotem na format dziesiętny, wynik może nieco różnić się od oczekiwanego. To jest przyczyną, dla której operacje takie jak dodawanie 0.1
i 0.2
w programowaniu nie dają dokładnie 0.3
, lecz nieco inną wartość.
W praktyce te drobne różnice mogą się kumulować, szczególnie w skomplikowanych obliczeniach lub w operacjach, które wykonujemy wielokrotnie. W rezultacie, w zastosowaniach wymagających dużej precyzji, takich jak finanse, te błędy mogą mieć znaczący wpływ.
Jak unikać tych błędów?
W przypadku obliczeń finansowych, zaleca się przechowywanie i operowanie na liczbach całkowitych zamiast zmiennoprzecinkowych. Na przykład, zamiast przechowywać kwoty jako złotówki i grosze (np. 1,55 zł), przechowuje się je jako najmniejszą jednostkę (np. 155 groszy). Dzięki temu unikniesz błędów zaokrągleń, które często pojawiają się przy liczbach zmiennoprzecinkowych.
Używanie Metod toPrecision()
i toFixed()
toPrecision()
Ta metoda określa, ile cyfr liczby należy zachować. Na przykład:
var num = 12345.6789;
//W tym przypadku toPrecision(6) zaokrągla liczbę do 6 cyfr.
var formattedNum = num.toPrecision(6);
console.log(formattedNum); // Wynik: "12345.7"
toFixed()
Ta metoda określa, ile miejsc po przecinku należy zachować. Na przykład:
var num = 12345.6789;
//Tutaj toFixed(2) zaokrągla liczbę do dwóch miejsc po przecinku.
var formattedNum = num.toFixed(2);
console.log(formattedNum); // Wynik: "12345.68"