Obliczanie pola trójkąta - problem z instr. if

0

Witam, mam następujący problem z jednym programem. Program ma obliczać pole trójkąta, ale tylko wtedy, gdy jest to trójkąt prostokątny. Mam już zdefiniowane warunki i cały mechanizm matematyczny, jednak problem dotyczy pogrubionego fragmentu kodu:

#include <cstdlib>
#include <math.h>
#include <iostream>

using namespace std;

class trojkat
{
      private:
        struct point
        {
          float x;
          float y;
        };
        point p1,p2,p3;
        float dl1,dl2,dl3;
        float pole;
        bool zapytanie;
      public:
      void wprowadz();
      void sprawdz();
      void oblicz();
      void wypisz();
};

void trojkat::wprowadz()
{
         cout<<"Podaj wsp. wierzch. a "<<endl;
         cin>>p1.x;
         cin>>p1.y;
         cout<<"Podaj wsp. wierzch. b "<<endl;
         cin>>p2.x;
         cin>>p2.y;
         cout<<"Podaj wsp. wierzch. c "<<endl;
         cin>>p3.x;
         cin>>p3.y;
}
void trojkat::sprawdz()
{
      float bok1x=0, bok1y=0, bok2x=0, bok2y=0, bok3x=0, bok3y=0;
      bok1x=pow((p2.x-p1.x),2);
      bok1y=pow((p2.y-p1.y),2);
      bok2x=pow((p3.x-p2.x),2);
      bok2y=pow((p3.y-p2.y),2);
      bok3x=pow((p3.x-p1.x),2);
      bok3y=pow((p3.y-p1.y),2);
      
      dl1=sqrt( bok1x + bok1y );
      dl2=sqrt( bok2x + bok2y );
      dl3=sqrt( bok3x + bok3y );
      
      float pot1=0,pot2=0,pot3=0;
      pot1=dl1*dl1;
      pot2=dl2*dl2;
      pot3=dl3*dl3;
      //cout<<"roznica wsp. do potegi"<<endl;
      //cout<<"bok1x="<<bok1x<<" bok1y="<<bok1y<<" bok2x="<<bok2x<<" bok2y="<<bok2y<<" bok3x="<<bok3x<<" bok3y="<<bok3y<<endl;
      //cout<<"Potegi:"<<endl;
      cout<<"\npot1="<<pot1<<", pot2="<<pot2<<", pot3="<<pot3<<"\n";
      
      **if ( pot1+pot2==pot3 || pot2+pot3==pot1 || pot1+pot3==pot2 )
         zapytanie=true;
      else
          zapytanie=false;
}
void trojkat::oblicz()
{
     //cout<<"warunek="<<zapytanie<<endl;
     cout<<"pierwszy bok: "<<dl1<<", drugi bok: "<<dl2<<", trzeci bok: "<<dl3<<endl;
     
     if (zapytanie==true && dl1*dl2*dl3!=0)
     {
         float p=0;
         p=0.5*(dl1+dl2+dl3);
         pole=sqrt(p*(p-dl1)*(p-dl2)*(p-dl3));
     } 
     if (zapytanie==false || dl1*dl2*dl3==0)
     {
        cout<<"trojkat o podanych wspolrzednych wierzcholkow nie istnieje,\nalbo nie jest prostokatny"<<endl;
     }
} **
void trojkat::wypisz()
{
      if (zapytanie==true && dl1*dl2*dl3!=0)
      {
         cout<<"Pole trojkata wynosi: "<<pole<<endl;
      }
      //if (zapytanie==false)
      else
      {             
         cout<<"";
      }
}

int main(int argc, char *argv[])
{
    int decyzja=1;
    do {
        
        trojkat figura;
        figura.wprowadz();
        figura.sprawdz(); 
        figura.oblicz();
        figura.wypisz();
        
        cout<<"\nCzy jeszcze raz? (0/1)"<<endl;
        cin>>decyzja;
        system("cls");
        if (decyzja==0) break;
    }
    while (decyzja==1);
        
    system("PAUSE");
    return EXIT_SUCCESS;
}

Zdarzają mi się takie sytuacje, gdy warunek w pogrubieniu jest spełniony a mimo to zmienna zapytanie dostaje wartość false. Czy ktoś ma jakiś pomysł aby to naprawić, albo gdzie jest błąd w moim kodzie?

0

Podaj jakieś konkretne dane przy których jest zły wynik. Albo użyj debugera. On wie wszystko.
OK. Wiem, o co chodzi. Gdy masz ładny przykład, gdzie trzy długości boków są liczbami całkowitymi działa, w przeciwnym wypadku nie. Pomyśl dlaczego.

0

Przykładowo, jeśli podam takie współrzędne:
(0,0), (3,0), (0,4), to wszystko gra i oblicza.
Natomiast jeśli wklepie mu takie coś np. :
(1,1), (2,2), (2,1) to już go nie przepuszcza.

Problem w tym programie dotyczy tylko tego warunku, gdzie mamy coś a la tw. Pitagorasa. Reszta tzn. obliczenia matematyczne są dobre i do nich nie mam zastrzeżeń.

0

Ja bym strzelał, że chodzi o dokładność float-ów (i innych). W przypadku pierwszym masz długości równe (3, 4, 5) - wszystko zostaje zachowane OK. W drugim przypadku masz już boki długości (1, 1, 1.41421356...) - i ta ostatnia liczba będzie zaokrąglona; przy podniesieniu do potęgi 2 da coś w rodzaju 1.999999999999.

Dwa wyjścia:

  • a) z Pitagorasa otrzymujesz (długość_krawędzi)^2; do sprawdzenia potrzebujesz jedynie tych kwadratów. Dopiero w części obliczeniowej możesz liczyć sobie długości krawędzi bez "drugiej potęgi".
  • b) zakładasz możliwe błędy pomiaru (patrz np. tutaj: http://edu.i-lo.tarnow.pl/inf/utils/001_2008/0119.php)
0

hmm.. właśnie po podniesieniu liczby niewymiernej do kwadratu nie ma żadnego problemu z zaokrąglaniem. Kiedy podniosłem 1.41421... do kwadratu to otrzymałem na ekranie konsoli śliczne, wymierne 2, a nie 1.999999... także to chyba nie to...

0
gość napisał(a)

hmm.. właśnie po podniesieniu liczby niewymiernej do kwadratu nie ma żadnego problemu z zaokrąglaniem. Kiedy podniosłem 1.41421... do kwadratu to otrzymałem na ekranie konsoli śliczne, wymierne 2, a nie 1.999999... także to chyba nie to...

To śliczne dwa może być przechowywane jako 1.(9)... tak samo jak bodajże double 0,1*100 jest różne od int 10.. Możesz dać jakieś E jako margines błędu..

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