Chyba problem IEEE 754?

0

Chcę wymusić aby użytkownik w formularzu podawał dane do dwóch miejsc po "przecinku". Nawet jeśli poda więcej to formularz obcina wszystko co dalej. Nie chodzi o zaokrąglanie tylko proste usuwanie aby użytkownik widział co od niego wymagamy. Myślałem, że załatwię to za pomocą:

kwota = (Math.floor(kwota * 100)) / 100;

Niestety dla niektórych przypadków wychodzą dziwne wyniki np wpisanie 17.99 daje w efekcie 17.98

Czy jest jakiś prosty sposób żeby sobie z tym poradzić?

3

To nie jest problem z IEEE 754 tylko problem z niezrozumieniem tego standardu. Nie da się zapisać każdej liczby rzeczywistej w tym standardzie wiec są zaokrąglenia. Jak chcesz mieć precyzyjną wartość to trzymaj to jako String lub użyj biblioteki do licz większej precyzji (używają one więcej pamięci wiec mogą przechowywać dokładniejsze wartości)

2

Jeżeli liczba jest zawsze z dokładnością do 2 miejsca po przecinku, to zawsze można pomnożyć przez 100 i przechowywać jako zaokrągloną liczbę całkowitą, a do wyświetlenia podzielić przez 100. Odpada problem z dokładnością kosztem nieco skomplikowania obliczeń.

0

@Pesob:

Pesob napisał(a):

Czy jest jakiś prosty sposób żeby sobie z tym poradzić?

Gdyby to było vue to wystarczy https://element-plus.org/en-US/component/input-number.html#precision
Jak nie, to można podejrzeć jak tam jest zrobione. Zapewne trzymane w stringu i odpowiednio oskryptowane.

0

@szatkus: Dzięki wielkie za pomoc

kwota = parseFloat(kwota.replace(/(\d+\.\d\d)\d*/, '$1'))

Mam nadal liczbę i nie ma tych "dziwnych" wyjątków.

@andrzejlisek: No właśnie o tym piszę, że to nie działa. 17.99 razy 100 podzielone przez 100 daje 17.98.

@KamilAdam: Dla worka z mięsem sprowadza się to do problemu :)

0

@andrzejlisek: No właśnie o tym piszę, że to nie działa. 17.99 razy 100 podzielone przez 100 daje 17.98.

Zamiast mnożyć i dzielić przez 100 można z tego wybrnąć, jak napiszesz dwie własne funkcje. Pierwsza przyjmuje tekst i zwraca liczbę większą 100 razy i zaokrągloną do całości lub NaN w przypadku, gdy tekst nie daje się zamienić na liczbę. Twoja funkcja na poziomie tekstu musi znaleźć przecinek, usunąć cyfry stojące dalej niż na drugim miejscu, sprawdzić, czy wpisany ciąg w ogóle jest liczbą.

Druga funkcja przyjmuje liczbę i zamienia na tekst. Już na poziomie tekstu można odliczyć dwie cyfry od końca (ewentualnie dopisać zera z przodu) i wpisać przecinek.

Przy takim podejściu odpadnie problem zmiany wartości spowodowanej zaokrągleniami i właściwościami IEEE754.

1 użytkowników online, w tym zalogowanych: 0, gości: 1