Porównywanie liczb zmiennoprzecinkowych

0

Witam. Jestem początkującym programistą i proszę o pomoc. Chcę porównać dwie liczby typu double. Na jednym forum przeczytałem:

"a=0
b=0
( a==b ) zwróci false, ponieważ
a= 0.0000001234
b= -0.0000000567

(przykład nie zachodzi, jeśli go skompilujesz, ale ukazuje problem, ideę)
Ponieważ liczby rzeczywiste posiadają reprezentację przybliżoną"

Czy rzeczywiście jest tak, że nie można porównywać ze sobą dwóch liczb typu zmiennoprzecinkowego (nawet jeśli powinny być równe), bo posiadają reprezentację przybliżoną? W różnych źródłach czytałem, że takie porównanie nie ma sensu. Ale sprawdziłem to w Dev-C++ i zwraca true, a nie false jak podobno miało zwrócić, a wypisując liczby a oraz b otrzymujemy równe 0, a nie coś bliskiego 0.

2

Odnośnie 0 to: http://4programmers.net/Forum/Newbie/154547-zaokraglenia_w_double_a_wartosc_00
Prawdopodobnie, gdy przypiszesz takie same stałe do zmiennych np. a = 1.23; oraz b = 1.23; to prawdopodobnie też będziesz miał true -> zaokrąglenie powinno wyjść takie samo.
Problem pojawi się jednak, gdy masz wiele operacji na jakiejś zmiennej i nigdy nie będziesz mógł być pewny jak ona została zaokrąglona (czy tak samo jak zmienna z którą porównujesz).
Co ciekawe double A,B,C; ... (A + B) + C != (A + C) + B; (przynajmniej może zaistnieć taka nierówność).

1

Czy rzeczywiście jest tak, że nie można porównywać ze sobą dwóch liczb typu zmiennoprzecinkowego (nawet jeśli powinny być równe), bo posiadają reprezentację przybliżoną?

Jeśli posiadają reprezentacje przybliżoną to tak - mogą wystąpic błędy. To jest tak, ze przeciez fizycznie mamy mamy ilestam bitow, i na tych bitach zapisujemy liczby. Może okazać się ich zbyt mało. To zawsze było bolączką C++ i kompilatory i optymalizatory z tym walczą. I tak dla prostych wyrażen:
http://ideone.com/iRBofu
wszystko jest okej, choc nie zapiszemy 1/3 dokładnie. Wystarczy jednak nieco to skomplikować i "nie dać działac optymalizatorowi" poprzez wprowadzenie z klawiatury większosci danych.
http://ideone.com/ZNg5zc
Podobnie sprawa ma się np. z liczeniem pierwiastka n-tego stopnia. W takich obliczeniach zazwyczaj przyjmujemy jakis epsilon - przybliżenie w algorytmie dynamicznym. Algorytm konczymy, gdy |Xn - Xn-1| < epsilon, co oczywiscie nie daje wartosci dokładnej. Najgorzej sprawa ma się z odejmowaniem liczb, ktore mają bardzo bliskie wartosci. Wtedy dopiero sie cuda dzieją. Uwierz mi, ze na zadaniu "oblicz pierwiastki rownania kwadratowego" zdecydowana wiekszosc sie wyłoży, bo ich wyniki będą bardzo przybliżone.

4

Daleko nie trzeba szukać: 0.1 + 0.1 == 0.2 zwróci true, a 0.1+ 0.1 + 0.1 == 0.3 zwróci false.

1

Czesc, mialem jakis czas temu z tym problem, tu masz odpowiedz http://cpp0x.pl/forum/temat/?id=13171

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