[JS] Błędny wynik działania 1.1 - 1 = 0.10000000000000009


(look997) #1

Co to za błędy?

Jak to naprawić?

1.1 - 1 = 0.10000000000000009

1.0000001+1 = 2.0000001000000003


(stasinek) #2

Wyjaśnienie przyczyny jest tu http://docs.python.org/release/2.5.1/tut/node16.html

(mimo że to python)

dzieki za pytanie bo nie zastanawiałem sie nigdy nad tym :stuck_out_tongue:

konkretnie: liczba dziesietna 0.1 to bitowo>

0.0001100110011001100110011001100110011001100110011...

jeśli zatrzymasz przybliżanie 0.1 na jakimkolwiek bicie otrzymasz przybliżenie >>> 0.1

0.10000000000000001

zatem to wynik przybliżenia w zapisie liczb dziesietnych przy użyciu liczb w systemie dwójkowym np. 0.25,0.125, 0.0625 itd. a zatem "binarne" ułamki 1/4,1/8,1/16 - żaden z nich nie da przybliżeń w zapisie dwójkowym ale liczba 0.1, 0.01 to nienaturalna liczba dla zapisu dwójkowego i już na etapie zapisu "w komputerze" jest przybliżeniemhttp://stackoverflow.com/questions/1458 ... er-problem

function round_up( value, precision ) { 

    var pow = Math.pow ( 10, precision ); 

    return ( Math.ceil ( pow * value ) + Math.ceil ( pow * value - Math.ceil ( pow * value ) ) ) / pow; 

}

round_up(341.536, 2); // 341.54

lub

var fpArithmetic = function (op, x, y) {

    var n = {

            '*': x * y,

            '-': x - y,

            '+': x + y,

            '/': x / y

        }[op];        


    return Math.round(n * 100)/100;

};


fpArithmetic('*', 0.1, 0.2);

// 0.02

fpArithmetic('+', 0.1, 0.2);

// 0.3

fpArithmetic('-', 0.1, 0.2);

// -0.1

fpArithmetic('/', 0.2, 0.1);

najlepiej nie używać liczb zmiennoprzecinkowych, wykonywać obliczenia na stałoprzecinkowym po przemnożeniu liczb do wymaganej precyzji przez stały przelicznik np. x1000 aby unikać dzieleń przybliżań, gdyby chodziło o super wydajność i nie javascript używalbym przesuniecia bitowego(mnożenia i dzielenia w systemie dwójkowym) w lewo a póxniej w prawo(np. o 8 bitów - 256) bo operacja zajmuje jeden cykl procesora podczas gdy operacja mnożenie zajmuje 4 a dzielenie 12 cykli procesora(x86)

PS np. kompresja arytmetyczna która polega na zapisie treści dowolnej wiadomości przy pomocy bardzo dużej liczby zmiennoprzecinkowej, metoda wogóle nie używa zmiennoprzecinkowych, śp. rozszerzenia w procesorach Intel MMX, AMD 3DNow! to rozszerzenia stałoprzecinkowe.


(Semtex) #3

Witaj, popraw proszę tytuł tematu tak aby wstępnie informował o problemie, użyj przycisku EDYTUJ , który znajdziesz w prawym górnym rogu Swojego posta. Dobrze zatytułowany temat daje szansę na szybszą pomoc. Dziękuję za uwagę.

Tip: Unikaj słów: "problem", "help", "pomocy" i.t.p. Tego typu słowa nie spowodują szybszej reakcji a mogą odnieść odwrotny skutek od oczekiwanego, tytuł tematu ma być skróconym opisem Twojego posta- powodzenia.


(kostek135) #4

Generalnie dodam od siebie, żebyś wpisał w Google -> "BigDecimal JS", i po prostu wybrał sobie jakąś bibliotekę, która pozwala na operacje z dowolną (ograniczeniem jest pamięć) dokładnością.