Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

granica błędu i błąd w badaniu wartości bezwzględnej różnicy

Ostatnio zmodyfikowano 2020-06-13 15:39
Autor Wiadomość
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
C/C++
#include <iostream>
#include <iomanip>      //fixed, setprecision(2)
#include <fstream>
#include <cmath>        //fabs
#include <cstring>      //strlen
#include <vector>
#include <algorithm>
#include <limits>       //std::numeric_limits
#include <sstream>      //std::stringstream

using namespace std;

int main()
{
    double x { 0 }, y { 0 };
    const double granica = 1.0 / 100; //wartosc graniczna, granica bledu
   
    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() )
        {
            //czyscimy strumien wejsciowy std::cin
            std::cin.clear();
            std::cin.ignore( std::numeric_limits < std::streamsize >::max(), '\n' );
            cout << "podany argument nie spelnia zalozenia" << endl;
            break;
           
        } else {
            //czyscimy strumien wejsciowy std::cin
            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 ) ) //|| (fabs(y-x)<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
P-177042
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.
C/C++
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.
P-177043
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.
P-177048
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
C/C++
double wynik { 0 };
float e = std::numeric_limits < float >::epsilon() + granica;
//cout << "\ne " << e << endl;
( fabs( wynik = x - y ) <= e ) ?( cout << "sa prawie rowne" << endl )
    :( cout << "roznia sie" << endl );
P-177104
« 1 »
  Strona 1 z 1