Porownywanie zmiennych real

0
procedure TForm1.Button5Click(Sender: TObject);
var
  a, b, d, e : real;
  c : integer;
begin
  a := 0.3; //Pierwszy
  b := 0.5; //Drugi
  d := 0;
  e := 0;
  for c := 1 to 10 do
    begin
      if ((a+d*a) = (b+e*b)) then
      begin
        memo1.Lines.add('atakuja oboje');
        d := d + 1;
        continue;
      end;
      if ((a+d*a) > (b+e*b) = True) then
      begin
        memo1.Lines.add('atakuje Drugi');
        e := e + 1;
        continue;
      end;
      if ((a+d*a) < (b+e*b) = True) then
      begin
        memo1.Lines.add('atakuje Pierwszy');
        d := d + 1;
        continue;
      end;
    end;
end;

Problem zaczyna się, gdy a+da i b+eb dochodzą do wartości 1,5. Zamiast wejść w tego ifa if ((a+da) = (b+eb)) then to nagle wchodzi do tego ifa if ((a+da) < (b+eb) = True) then. Nie mam pojęcia dlaczego, więc pytam.

0

znany problem w delphi.. czasami nawet 0 nie jest równe 0...
debugger wyświetla ileś tam liczb po przecinku, a w rzeczywistości na końcu zdarza się że jest jakiś śmieć który zniekształca wyniki..
najlepiej jeśli tylko można zastosować zaokrąglanie liczb...

0

nie wiem o co Ci wlasciwie chodzi ale czepne sie Twojego kodu....
nie wiem po co dajesz "(a+da) > (b+eb) = True". to porownanie z true nie jest potrzebne.
teraz troche bardziej czytelne:

var
  a, b, d, e : real;
  c : integer;
  pierwszy,drugi:Real;
begin
  a := 0.3;
  b := 0.5;
  d := 0;
  e := 0;

  for c := 1 to 10 do
    begin
     pierwszy:=(a+d*a);
     drugi:=(b+e*b);

     if (pierwszy = drugi) then
         begin
          memo1.Lines.add('atakuja oboje');
          d := d + 1;
          continue;
         end;

     if (pierwszy > drugi) then
         begin
          memo1.Lines.add('atakuje Drugi');
          e := e + 1;
          continue;
         end;

     if (pierwszy < drugie) then
         begin
          memo1.Lines.add('atakuje Pierwszy');
          d := d + 1;
          continue;
         end;
    end;
end;
0

@cimak - teraz działa. Zawsze mam taki śmietnik w kodzie (jak zaczynam coś robić). Tylko dlaczego to działa, a tamto nie?
(a+da) > (b+eb) = True - dałem to, bo wywalało mi błąd. Jednak okazuje się, że to przez nawiasy (za mało).
To jeszcze dodatkowo zapytam: czy w Delphi 7 jest jakaś pomoc do nawiasów? Tzn. zaznaczanie który do którego, bo jak mam za dużo nawiasów to się gubię.

0

w samym delphi nie. sa jakies dodatki, sam mialem je doinstalowac, mozliwe ze one pomagaja... zerknij tu:
http://4programmers.net/Forum/594150?h=wasze%20delphi#id594150
jelsi chodzi o gubienie sie w nawiasach czy ilosci begin-end.. jest prosta metoda:
jak otwierasz to od razu zamykaj... zamiast pisac: (bla bla bla... i na koncu pamietac o ")" napisz () i potem w srodek wstawiaj tresc.

P.S. a dlaczego dziala? a hgw. pewnie to wina delphi, lepiej sie zabezpieczyc, tak jak napisal zajcev.

0
cimak napisał(a)

w samym delphi nie. sa jakies dodatki, sam mialem je doinstalowac, mozliwe ze one pomagaja... zerknij tu:
http://4programmers.net/Forum/594150?h=wasze%20delphi#id594150
Dzięki wielkie, bardzo mi się przydadzą, bo już parę poinstalowałem i teraz wszystko ładnie zaznacza.

cimak napisał(a)

lepiej sie zabezpieczyc, tak jak napisal zajcev.
Ale jak zaokrąglać do paru miejsc po przecinku?

0

masz dwie mozliwosci:

  1. poszukac w internecie to znajdziesz w 3 sek.
  2. pomnozyc wynik np przez 1000, potem albo zaokraglic round() albo uciac to co za przecinkiem trunc() i wtedy porownywac.
0
  1. zaokrąglanie - uses math; rounto();
  2. porównanie liczb rzeczywistych - if Abs(a - b) < 0.000001 then TAKIE_SAME;
    0.000001 - to dokładność z jaką chcesz porównywać liczby
0

W podanum w pierwszym poscie przypadku nie bardzo widze możliwość, żeby pojawiły się wartości tak daleko po przecinku. Stawiam, że to jest kwestia kolejnosci przetwarzania warunków - przy tak ustawionych nawiasach nie wiadomo gdzie jest lewa, a gdzie prawa strona porownania - to znaczy czy lewa jest to co jest przed znakiem wiekszy-mniejszy czy przed znakiem rownosci.

Poza tym - nie wiem po jaką cholerę używać instrukcji continue, zamiast dla swojej wygody i czytelności użyć ludzkiej instrukcji "else".

Wykonajcie poniższy kod:

var
  a, b, d, e : real;
  c : integer;
  pierwszy,drugi : Real;
begin
    a := 0.3; //Pierwszy
    b := 0.5; //Drugi
    d := 0;
    e := 0;
    for c := 1 to 10 do begin
        pierwszy:=a+d*a;
        drugi:=b+e*b;
        if pierwszy=drugi then begin
            Memo1.Lines.add('atakuja oboje');
            d := d + 1;
        end else
        if pierwszy > drugi then begin
            Memo1.Lines.add('atakuje Drugi');
            e := e + 1;
        end else
        if pierwszy < drugi then begin
            Memo1.Lines.add('atakuje Pierwszy');
            d := d + 1;
        end;
        Memo1.Lines.Add('pierwszy: '+FloatToStr(pierwszy)+', drugi: '+FloatToStr(drugi)+', c: '+IntToStr(c));
    end;
end;

Okazuje się, że wartości jakie się pojawiają mają dokładność rzędu jednego miejsca po przecinku.

Generalnie jeżeli mogę coś zasugerować, to zanim zaczniesz cokolwiek pisać - rozrysuj to sobie na kartce i postaraj sie nie robić bałaganu we własnym kodzie. Za czasów studiów tłukli nam do głowy technikę SWYM: Say What You Mean - czyli pisz dokładnie to, co chcesz, żeby komputer zrobił i nie pozostawiaj miejsca na domysły. Kompilator nie zawsze interpretuje kod w taki sposób jak Ty go widzisz (nie mówiąc już o tym, że kompilator technicznie widzi kod zupełnie inaczej niż edytor - niektórzy pamiętają mój przypadek z błedną interpretacją kodu końca linii - edytor widzi 0D jak 0D0A, a kompilator tak jak jest na prawde = 0D)

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