granica błędu i błąd w badaniu wartości bezwzględnej różnicy
Ostatnio zmodyfikowano 2020-06-13 15:39
nanoant20 Temat założony przez niniejszego użytkownika |
granica błędu i błąd w badaniu wartości bezwzględnej różnicy » 2020-06-11 18:31:29 dla podanych par wartości np. 10.49 i 10.5 <= wynik taki jaki oczekuję poprawny 21 i 20.99 <= wynik fałszywy 1.5 i 1.49 <= wynik fałszywy 3.21 i 3.20 <= wynik poprawny Why? Podaje najprostsza wersję programu #include <iostream> #include <iomanip> #include <fstream> #include <cmath> #include <cstring> #include <vector> #include <algorithm> #include <limits> #include <sstream>
using namespace std;
int main() { double x { 0 }, y { 0 }; const double granica = 1.0 / 100; cout << fixed << setprecision( 2 ); cout << "wartosc graniczna, granica bledu " << granica << endl; cout << "Podaj dwie liczby rzeczywiste. Znak rozny od liczby konczy program : "; cin >> x >> y; while( 1 ) { if( cin.fail() ) { std::cin.clear(); std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); cout << "podany argument nie spelnia zalozenia" << endl; break; } else { std::cin.clear(); std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); cout << "Twoje liczby to " << x << " " << y << endl; if(( fabs( x - y ) < granica ) ) { cout << "Liczby " << x << " i " << y << " sa prawie rowne" << endl; } else if( x < y ) { cout << "Mniejsza liczba to " << x << endl; cout << "Wieksza liczba to " << y << endl; } else { cout << "Mniejsza liczba to " << y << endl; cout << "Wieksza liczba to " << x << endl; } std::cout << "Podaj dwie liczby rzeczywiste. Znak inny od liczby konczy program : "; cin >> x >> y; } } cout << "Koniec programu. Bye." << endl << endl; getchar(); return 0; }
//EDIT W praktyce wynik będzie trochę powyżej lub poniżej progu i to właśnie widzisz jako spełnienie, lub nie spełnienie warunku. |
czyli mam rozumieć, że zawsze będzie istniał pewien błąd |
|
pekfos |
» 2020-06-11 18:45:02 10.49 i 10.5 <= wynik taki jaki oczekuję poprawny 21 i 20.99 <= wynik fałszywy 1.5 i 1.49 <= wynik fałszywy 3.21 i 3.20 <= wynik poprawny |
Wszystkie wyniki są poprawne, to Twoje oczekiwania są błędne. if(( fabs( x - y ) < granica ) )
Tolerancja w tym warunku jest po to, by nie testować równości dwóch liczb zmiennoprzecinkowych. Gdy masz dwie liczby które powinny się różnić dokładnie o wartość progową, to efektywnie próbujesz testować tu równość liczb. W praktyce wynik będzie trochę powyżej lub poniżej progu i to właśnie widzisz jako spełnienie, lub nie spełnienie warunku. |
|
jankowalski25 |
» 2020-06-11 20:47:11 czyli mam rozumieć, że zawsze będzie istniał pewien błąd |
W przypadku liczb zmiennoprzecinkowych? Tak. Jak chcesz mieć wyniki z dokładnością co do 0.01 , to możesz liczyć na liczbach całkowitych i robić liczba / 100 , żeby uzyskać wartość przed kropką i liczba % 100 , żeby uzyskać wynik po kropce. A jak chcesz używać liczb zmiennoprzecinkowych, to musisz nieco zmodyfikować tamtą linijkę, gdzie sprawdzasz, czy wynik jest mniejszy od epsilona. Jak dasz wyższą wartość w setprecision() , to jako wynik fabs( x - y ) zobaczysz na przykład 0.009999999999999786837179271970 albo 0.010000000000001563194018672220 , czyli odpowiednio wynik nieco mniejszy i nieco większy od 0.01 , dlatego raz wejdziesz w if , a drugi raz w else . Żeby to poprawić, możesz na przykład odjąć 0.01 i jeszcze raz wywołać fabs() , bo wtedy weźmiesz wartość bezwzględną z wyniku oscylującego w okolicach zera i wtedy porównanie z epsilonem ma sens. |
|
nanoant20 Temat założony przez niniejszego użytkownika |
» 2020-06-13 15:39:40 @pekfos dziękuję za odpowiedź @jankowalski25 dziękuję za naprowadzenie - słowem klucz stało się słowo "epsilon"zacząłem robić to na liczbach całkowitych, ale zaczęła się akrobatyka w kodzie i zrobiłem to inaczej, moje rozwiązanie double wynik { 0 }; float e = std::numeric_limits < float >::epsilon() + granica;
( fabs( wynik = x - y ) <= e ) ?( cout << "sa prawie rowne" << endl ) :( cout << "roznia sie" << endl );
|
|
« 1 » |