Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler beim Runden (https://www.delphipraxis.net/141135-fehler-beim-runden.html)

woibauer 3. Okt 2009 10:48


Fehler beim Runden
 
Warum rundet das Programm falsch ???

Aufgabe war die Dreiecksberechnung ohne Math-Unit zu benutzten


Delphi-Quellcode:
program Dreieck; {$APPTYPE CONSOLE} uses
  SysUtils;

var
  s, fa: integer;
  a, b, c, alpha_r, alpha_d, h, f, u: real;
  h_s, f_s, a_s, u_s, c_s, b_s, alpha_d_s: string;
  x: char;

const
  phi = 3.14159265358979323846264;

begin
  Repeat

  begin
    Writeln(
      'Berechnung des Flaecheninhaltes, Umfanges, der anderen Seit und der Hoehe ');
    Writeln(
      'eines Dreiecks durch die Eingab von 2 Seiten und dem dazwischen liegendem Winkel');
    Writeln('Start mit Return-Taste');
    readln(x);
    write('Erste Seite (c) in cm = ');
    readln(c);
    write('Zweite Seite (b) in cm = ');
    readln(b);
    write('Der Winkel zwischen den beiden Seiten (alpha) = ');
    readln(alpha_d);
    write('Genauigkeit des Rundens (Stellen)');
    readln(s);
    case s of
      1:
        fa := 10;
      2:
        fa := 100;
      3:
        fa := 1000;
      4:
        fa := 10000;
      5:
        fa := 100000;
      6:
        fa := 1000000;
      7:
        fa := 10000000;
      8:
        fa := 100000000;
      9:
        fa := 1000000000;
      10:
        fa := 10000000000;

    else
      fa := 10000000000;
      Writeln('');
      Writeln('Programm ist zu ungenau. Es wird mit 10 Stellen gerechnet')
    end;

    if alpha_d < 180 then
    begin
      alpha_r := alpha_d * (phi / 180);
      h := sin(alpha_r) * b;
      f := 0.5 * c * h;
      a := sqrt(b * b + c * c - 2 * b * c * cos(alpha_r));
      u := a + b + c;
      c_s := FloatToStr(c);
      b_s := FloatToStr(b);
      alpha_d_s := FloatToStr(alpha_d);
      h_s := FloatToStr(round(h * fa) / fa);
      f_s := FloatToStr(round(f * fa) / fa);
      a_s := FloatToStr(round(a * fa) / fa);
      u_s := FloatToStr(round(u * fa) / fa);
      Writeln('');
      Writeln('Das Dreieck mit der Seite c ', c_s, ' cm');
      Writeln('und der Seite b ', b_s, ' cm');
      Writeln('und dem Winkel alpha ', alpha_d_s, ' in Grad');
      Writeln('hat einen Flaecheninhalt von ', f_s, ' cm im Quadrat');
      Writeln('und einen Umfang von ', u_s, ' cm');
      Writeln('');
      Writeln('die letzte Seite a betraegt ', a_s, ' cm');
      Writeln('und die Hoehe h ist ', h_s, ' cm');
      Writeln('');
      Writeln(h, ' h ', f, ' f ', a, ' a ', u, ' u');
    end
    else
      Writeln('Das Dreieck ist nicht berechenbar');
    Writeln('');
    Writeln('Zum Beenden # eingeben und mit Return bestaetigen');
    readln(x);
  end;
  Until x = '#' end.

hugo1990 3. Okt 2009 10:53

Re: Fehler beim Runden
 
Es wäre erst einmal schön zu wissen, wo und was das Programm denn falsch rundet.
Und zweitens sind bei der Verwendung von Fließkommazahlen Rundungsfehler nicht zu vermeiden.

himitsu 3. Okt 2009 10:54

Re: Fehler beim Runden
 
Was ist für dich falsch Runden?

(hab es kurz getestet und bei Genauigkeit 5 sind auch 5 Nachkommastellen rausgekommen)

sx2008 3. Okt 2009 18:10

Re: Fehler beim Runden
 
Es gibt verschiedene Arten zu runden.
Computer verwenden im allgemeinern das sog. Banker's rounding während du wahrscheinlich Kaufmännisches Runden erwartest.
Die Funktion Round() verwendet das Banker' rounding Verfahren.

PS: du verwendet den Datentyp REAL.
Dieser Datentyp ist in Delphi veraltet und relativ ungenau.
Ersetze real durch double (64bit) oder Extended (80bit)!

Wolfgang Mix 3. Okt 2009 18:21

Re: Fehler beim Runden
 
@woibauer

Die Funktionen round, div , mod und trunc könnten Dir evtl weiterhelfen

Codebeispiele findest Du z.B. hier
Gruß

Wolfgang

Matze 3. Okt 2009 20:40

Re: Fehler beim Runden
 
Zitat:

Zitat von sx2008
PS: du verwendet den Datentyp REAL.
Dieser Datentyp ist in Delphi veraltet und relativ ungenau.
Ersetze real durch double (64bit) oder Extended (80bit)!

Ist das wirklich so? Der Datentyp "real" ist nicht mehr zeitgemäß, das ist korrekt. Aber intern wird dieser meines Wissens aufgrund der Abwärtskompatibilität einfach durch ein "double" ersetzt und müsste somit genauso exakt arbeiten wie ein echter "double". Oder liege ich hier falsch?

himitsu 3. Okt 2009 21:02

Re: Fehler beim Runden
 
Real = Double (8 Byte),
aber man kann diesen aus Gründen der Abwärtskompatibilität via {$REALCOMPATIBILITY ON} als Real48 (6 Byte) definieren.

Medium 4. Okt 2009 05:07

Re: Fehler beim Runden
 
Und zu guter letzt sollte "phi" hier wohl besser "pi" heissen :)

Wolfgang Mix 4. Okt 2009 10:46

Re: Fehler beim Runden
 
Kaufmännisch Runden auf n Stellen würde ich zunächst so versuchen:

Delphi-Quellcode:
function round2(number:double;n:word):double;
begin
  case n of
      2:begin
          number:=number*100;
          number:=number+0.5;
          number:=trunc(number);
          result:=number/100;
        end;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var number:double;
begin
   number:=StrToFloat(Edit1.Text);
   Edit2.Text:=FloatToStr(round2(number,2));
end;

end.
Gruß

Wolfgang


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz