W equasion jest string z równaniem do obliczenia:
res = eval(equasion);
console.log("**=====**")
console.log(equasion);
console.log(res);
Oto console.log:
**=====**
100.3-20.1
80.19999999999999
Jak z tym walczyć...?
W equasion jest string z równaniem do obliczenia:
res = eval(equasion);
console.log("**=====**")
console.log(equasion);
console.log(res);
Oto console.log:
**=====**
100.3-20.1
80.19999999999999
Jak z tym walczyć...?
Zaokrąglać?
Nie da się.
Błąd nie ma też nic wspólnego z eval()
em. Swoją drogą: unikaj eval()
a niemal za wszelką cenę! Ja muszę go zastosować może raz na rok, a piszę w każdym projekcie tysiące linii JS.
Błąd zaokrągleń jest związany z tym, że w JavaScripcie nie ma typu Decimal, tj. typu stałoprzecinkowego o pełnej precyzji. Typ liczbowy implementuje standard IEEE 754 definiujący zapis liczb zmiennoprzecinkowych. W JavaScripcie używane są liczby zmiennoprzecinkowe o podwójnej precyzji, tj. 64-bitowe. Wspomniany standard, dość powszechnie używany, definiuje taką, a nie inną precyzję liczb i prowadzi ona do tak kuriozalnych przypadków, jak...
console.log(0.3 + 0.6); // 0.8999999999999999
Sorki!
edit: Oczywiście, de facto da się to ominąć. Zawsze można skorzystać z jakiegoś parsera liczb i wyrażeń arytmetycznych, np. operującego na stringach, i wszystkie takie obliczenia przepuszczać przez niego.
Gdy potrzebujesz wykonywać obliczenia o stałej precyzji, np. na pieniądzach, rozwiązaniem jest liczenie nie w złotówkach, tylko w groszach i całkowite uniknięcie przecinków.
jak już mówiono to nie wina eval a nawet javascriptu tylko kodowania liczb i ten problem występuje też w innych językach programowania
praktycznie żadna liczba nie jest zapisana w pamięci dokładnie tak jak powinna
użyj:
liczba.toPrecision(21);
żeby zobaczyć pełne dostępne rozwinięcie liczby
przykładowo:
(0.1).toPrecision(21) => "0.100000000000000005551"
(0.2).toPrecision(21) => "0.200000000000000011102"
(0.3).toPrecision(21) => "0.299999999999999988898"
(0.6).toPrecision(21) => "0.599999999999999977796"
jak widać ewentualne błędy się pojawiają zazwyczaj po 16tej cyfrze rozwinięcia
dlatego domyślnie Javascript zaokrągla wynik przy wyświetlaniu do pierwszych 16 cyfr po przecinku
no i tu jest haczyk taki że jeśli przykładowo dodajesz do siebie kilka liczb zapisanych z błędem (jak powyżej) to błędy się nasilają, kumulują i pojawiają się na znacznie wcześniejszych pozycjach co można zaobserwować na przykładzie:
0.3 + 0.6 = 0.299999999999999988898 + 0.599999999999999977796 = 0.899999999999999911182
po zaokrągleniu do 16 miejsca po przecinku: 0.8999999999999999
moim zdaniem powinno Cię zadowolić:
res = parseFloat(res.toPrecision(15));
które zaokrągli liczbę do 15 miejsca po przecinku (możesz wpisać w nawiasie mniejszą wartość jeśli błędy nadal się pojawiają lub jeśli po prostu nie potrzebujesz aż tak dokładnego rozwinięcia)
Zarejestruj się i dołącz do największej społeczności programistów w Polsce.
Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.