Jak obejść złe wyniki z liczbami zmiennoprzecinkowymi?

Jak obejść złe wyniki z liczbami zmiennoprzecinkowymi?
Gregorius
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 102
0

Mam taki problem w JavaScripcie:

Kopiuj
console.log(0.1 + 0.2);

powoduje zły wynik. To problem, iż w JS wszystkie liczby z kropką są zmiennoprzecinkowe. Teraz pytanie: jak zapobiec tym błędom obliczeniowym?

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
0

Nijak, po prostu niektórych liczb nie da się zapisać.
Możesz użyć zaokrąglenia (przy wyświetlaniu) lub jakiejś biblioteki do bignumów (a zanim zapytasz jakiej: UTFG).

Gregorius
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 102
0
Patryk27 napisał(a):

Nijak, po prostu niektórych liczb nie da się zapisać.
Możesz użyć zaokrąglenia (przy wyświetlaniu)

To mało pomocne przy np

Kopiuj
2.3 * 100;

Jeszcz dziwniejsze jest dla mnie, iż

Kopiuj
2.3e2

w przeciwieństwie do pierwszego daje poprawny wynik

Poszukam jakiejś protej bibliteki

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
0

No ale co to ma do rzeczy?
Arytmetyka na liczbach zmiennoprzecinkowych jest po prostu inna niż całkowitych, tyle.

Gregorius
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 102
0
Patryk27 napisał(a):

No ale co to ma do rzeczy?
Arytmetyka na liczbach zmiennoprzecinkowych jest po prostu inna niż całkowitych, tyle.

Tak odmienna iż najwyraźniej pomiedzy 100 a 10^2 jest aż taka różnica? Po prostu mnie to zdumiewa.

Patryk27
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Wrocław
  • Postów: 13042
0

Nie, pomiędzy liczbami całkowitymi zapisanymi jako floaty nie ma różnicy (są zawsze dokładne, chyba że wystąpi under/overflow), ale niekoniecznie zapiszesz liczbę 'z przecinkiem'.
Przykładowo nigdy nie uda Ci się zapisać idealnie 0.1 - to zawsze będzie 0.100000001490116119384765625 (plus minus, zależnie od użytego typu liczbowego - nie wiem, co zakłada standard JS), bo tylko na taką najbliższą reprezentację pozwala IEEE 754.


Jak chcesz, możesz napisać sobie własną prostą bibliotekę do precyzyjnych floatów - po prostu zapisuj liczby jako ułamki (`licznik/mianownik`, w takiej formie w jakiejś JS-owej pseudoklasie), wtedy każda operacja będzie dokładna (choć niekoniecznie wydajna, jeżeli chcesz liczyć miliony takich liczb na sekundę).
Koziołek
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Stacktrace
  • Postów: 6823
0

@Patryk27 po co pisać? Już jest https://github.com/jtobey/javascript-bignum

@Gregorius to samo będzie i w C++ i w Javie i w asmie. Po prostu ten typ tak ma :) Jednym z rozwiązań (poza bibliotekami typu big num) jest użycie arytmetyki na liczbach całkowitych (pod warunkiem, że nie wykonujesz dzielenia) i formatowanie ich przy wyświetlaniu.

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.