Błędy Zaokrąglania?

W moim kursie powiedziano mi:

Wartości ciągłe są reprezentowane w przybliżeniu w pamięci, a zatem obliczanie za pomocą pływaków wiąże się z błędami zaokrąglania. Są to niewielkie rozbieżności we wzorcach bitowych, dlatego test {[0] } jest niebezpieczny, jeśli e i f są pływakami.

Odnosi się do Javy.

Czy to prawda? Używałem porównań z double s I float s I nigdy nie miałem problemów z zaokrągleniem. Nigdy nie czytałem w podręczniku czegoś podobnego. Na pewno konta wirtualnej maszyny?
Author: Sildoreth, 2009-06-06

9 answers

To prawda.

Jest nieodłącznym ograniczeniem sposobu reprezentacji wartości zmiennoprzecinkowych w pamięci w skończonej liczbie bitów.

Ten program, na przykład, wypisuje "false":

public class Main {
  public static void main(String[] args) {
    double a = 0.7;
    double b = 0.9;
    double x = a + 0.1;
    double y = b - 0.1;
    System.out.println(x == y);
  }
}

Zamiast dokładnego porównania z '= = 'zazwyczaj decydujesz się na pewien poziom precyzji i pytasz, czy liczby są "wystarczająco blisko":

System.out.println(Math.abs(x - y) < 0.0001);
 46
Author: Chris Vest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 17:37:30

Dotyczy to Javy tak samo jak każdego innego języka używającego zmiennoprzecinkowego. Jest nieodłącznym elementem projektowania reprezentacji wartości zmiennoprzecinkowych w sprzęcie.

Więcej informacji o wartościach zmiennoprzecinkowych:

Co Każdy Informatyk Powinien Wiedzieć O Arytmetyce Zmiennoprzecinkowej

 24
Author: Ben Schwehn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-20 08:11:24

Tak, reprezentowanie 0,1 dokładnie w bazie 2 jest tym samym, co próba reprezentowania 1/3 dokładnie w bazie 10.

 7
Author: duffymo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 16:50:36

To zawsze prawda. Istnieją pewne liczby, których nie można dokładnie przedstawić za pomocą reprezentacji punktów zmiennoprzecinkowych. Rozważmy, na przykład, pi. Jak reprezentowałbyś liczbę, która ma nieskończone cyfry, w skończonym magazynie? Dlatego porównując liczby należy sprawdzić, czy różnica między nimi jest mniejsza niż jakiś epsilon. Istnieje również kilka klas, które mogą pomóc w osiągnięciu większej dokładności, takich jak BigDecimal i BigInteger.

 4
Author: laginimaineb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 16:45:57

To prawda. Zauważ, że Java nie ma z tym nic wspólnego, problem tkwi w matematyce zmiennoprzecinkowej w dowolnym języku .

Często można ujść na sucho z problemami na poziomie klasy, ale to nie zadziała w prawdziwym świecie. Czasami to nie zadziała w klasie.

Incydent sprzed lat w szkole. Nauczyciel z klasy intro przydzielił do egzaminu maturalnego problem, który okazał się dla wielu lepszych uczniów prawdziwym kłopotem.nie działał i nie wiedzieli dlaczego. (Widziałem to jako asystenta laboratoryjnego, nie byłem w klasie.) W końcu niektórzy zaczęli mnie prosić o pomoc, a niektóre badania ujawniły problem: nigdy nie uczono ich o nieodłącznej nieścisłości matematyki zmiennoprzecinkowej.

Teraz, były dwa podstawowe podejścia do tego problemu, brute force jeden (który przez przypadek działał w tym przypadku, ponieważ popełniał te same błędy za każdym razem) i bardziej elegancki jeden (który popełniał różne błędy, a nie działa.) Każdy, kto próbował eleganckie podejście uderzyłoby w ceglany mur, nie mając pojęcia dlaczego. Pomogłem kilku z nich i utknąłem w komentarzu wyjaśniającym, dlaczego i skontaktować się ze mną, jeśli miał pytania.

Oczywiście w przyszłym semestrze usłyszę od niego o tym i w zasadzie rozwaliłem cały wydział prostym programem:

10 X = 3000000
20 X = X + 1
30 If X < X + 1 goto 20
40 Print "X = X + 1"
Pomimo tego, co myślał każdy nauczyciel na Wydziale, to zakończy się. 3 miliony nasion jest po prostu po to, aby zakończyć się szybciej. (Jeśli nie znasz podstaw: Nie ma tu żadnych sztuczek, tylko wyczerpuje precyzję liczb zmiennoprzecinkowych.)
 3
Author: Loren Pechtel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 16:54:20

Tak, jak mówiły inne odpowiedzi. Chcę dodać, że polecam ci ten artykuł o dokładności zmiennoprzecinkowej: Wizualizacja pływaków

 2
Author: Artur Soler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 16:48:51

Większość procesorów (i języków komputerowych) używa arytmetyki zmiennoprzecinkowej IEEE 754. Używając tej notacji, istnieją liczby dziesiętne, które nie mają dokładnej reprezentacji w tej notacji, np. 0.1. Więc jeśli podzielisz 1 na 10, nie otrzymasz dokładnego wyniku. Podczas wykonywania kilku obliczeń z rzędu błędy sumują się. Wypróbuj następujący przykład w Pythonie:

>>> 0.1
0.10000000000000001
>>> 0.1 / 7 * 10 * 7 == 1
False

To nie jest to, czego można się spodziewać matematycznie.

Przy okazji: Powszechne nieporozumienie dotyczące zmiennoprzecinkowego liczby są takie, że wyniki nie są precyzyjne i nie można ich bezpiecznie połączyć. Jest to prawdą tylko wtedy, gdy naprawdę używasz ułamków liczb. Jeśli cała Twoja matematyka jest w domenie całkowitej, podwaja i pływaki robią dokładnie to samo, co ints i mogą być bezpiecznie porównywane. Mogą być bezpiecznie używane na przykład jako Liczniki pętli.

 2
Author: Nikolai Ruhe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 17:14:31

Tak, Java używa również arytmetyki zmiennoprzecinkowej .

 1
Author: dfa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 16:46:16

Oczywiście, że to prawda. Pomyśl o tym. Każda liczba musi być reprezentowana w postaci binarnej.

Zdjęcie: "1000" jako 0,5 lub 1/2, czyli 2 * * -1. Następnie "0100" wynosi 0,25 lub 1/4. Widzisz, dokąd zmierzam.

Ile liczb możesz reprezentować w ten sposób? 2**4. Dodawanie kolejnych bitów powiela dostępną przestrzeń, ale nigdy nie jest nieskończona. 1/3 lub 1/10, dla sprawy 1 / n, żadna liczba nie wielokrotność 2 nie może być naprawdę reprezentowana.

1/3 może być "0101 "(0,3125) lub" 0110 " (0,375). Każda wartość, jeśli pomnożysz ją przez 3, nie będzie równa 1. Oczywiście możesz dodać specjalne zasady. Powiedz: "kiedy dodasz 3 razy '0101', zrób to 1"... takie podejście nie zadziała na dłuższą metę. Można złapać trochę, ale to może 1/6 razy 2?

Nie jest to problem reprezentacji binarnej, każda skończona reprezentacja ma liczby, których nie można reprezentować, w końcu są nieskończone.

 1
Author: eipipuz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-06 17:12:23