Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Sinus Wert ungenau!


BiG-BennY - Sa 28.02.09 22:49
Titel: Sinus Wert ungenau!
Hallo Freunde,

ich hab endlich meinen Rechner fertiggestellt und bin auch ziemlich glücklich damit.
Leider habe ich ein Problem, anstatt das bei Sinus 90 der Wert 1 rauskommt, kommt 0,9999999958 oder so rauß!

Was könnte das Problem sein?
Weitere Nullen bei der Wurzelberechnung sind nicht möglich, da sonst die Wurzel zu lange berechnet.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
procedure TGrundflaeche.SinusClick(Sender: TObject);
var b,s,z,w : Extended ;
const pi=3.1415926535897932384626433832795;
begin

  Zahl1 := StrToFloat(Anzeigefeld1W.Caption);

  b := ( Zahl1 / 1048576 );
  s := ((b*pi)/180);
  z := 20;

  WHILE z<>0 DO

    begin
    z := z-1;
    w := (1-(s*s));
    w := WurzelFunktion(w,2);
    s := (2*s*w);
    end;

  Ergebnisausgabe.Caption := FloatToStr(s);

end;


und die dazugehörige Funktion :


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
function Pot(b,e:Single):Single;
var v:Single;
begin

  IF e=0
    THEN Pot := 1
    ELSE begin
         v:=1;

         WHILE e > 0 DO

          begin
          v:=v*b;
          e:=e-1;
          end; // While Anweisungsblock

         Pot := v;
         end; // IF Anweisungsblock

end;

function WurzelFunktion(r:Extended;n:Cardinal):Extended;
var unten,mitte,oben:Extended;
begin

  IF r >= 1
    THEN begin
         unten:=1;
         oben:=r;
         end
    ELSE begin
         unten:=r;
         oben:=1;
         end;

    WHILE (( oben - unten ) > 0.0000000001 ) DO

      begin
      mitte := ((unten+oben)/2);
      IF Pot(mitte,n) > r
        THEN oben:=mitte
        ELSE unten:=mitte;
      end;

  WurzelFunktion := ((unten+oben)/2)

end;



mfG
Benny


Hidden - Sa 28.02.09 23:04

Hi :wave:

Das liegt an der Genauigkeit das Datentyps, würde ich mal sagen. Extended hat zwar sehr viele Nachkommastellen, aber du hast 20 Durchläufe, bei denen diese Ungenauigkeit quadratisch einfließt(w := 1 - (s*s)).

Ich nehme mal an, es handelt sich um ein Projekt? Ansonsten wären natürlich die vordefinierten, tabellenbasierten Funktionen genauer und schneller.

mfG,


Sirke - Sa 28.02.09 23:16

Ich kenne diese Näherung der Sinusfunktion nicht, jedoch eine andere die - wenn ich mich recht erinnere - auch ziemlich genau war!


Quelltext
1:
2:
3:
4:
5:
6:
7:
sin = 0
j = inputnumber

for i = 1 to 500 do
  sin = sin + j
  j = -j * x^2 / ( (2i + 1) * 2i )
end


... und es verzichtet auf die Wurzel ;-)


Reinhard Kern - Sa 28.02.09 23:26

user profile iconBiG-BennY hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Freunde,

ich hab endlich meinen Rechner fertiggestellt und bin auch ziemlich glücklich damit.
Leider habe ich ein Problem, anstatt das bei Sinus 90 der Wert 1 rauskommt, kommt 0,9999999958 oder so rauß!

Was könnte das Problem sein?
Weitere Nullen bei der Wurzelberechnung sind nicht möglich, da sonst die Wurzel zu lange berechnet.
...


Hallo,

deine Funktion Pot ist Single - das ist jetzt zwar keine qualifizierte Fehlerfortpflanzungsrechnung, aber grundsätzlich kannst du so nicht erwarten, dass dein Ergebnis besser ist als Single (so etwa ist es ja auch). Du musst schon alles mit der geforderten Genauigkeit rechnen.

Gruss Reinhard


BiG-BennY - So 01.03.09 00:42

So,

kleines Update -> Ich habs jetzt hinbekommen indem ich alles auf Extended umgestellt hab
und dann noch mit ffNumber die Nachkommastellen auf 9 begrenzt hab ^^ ( kleines Workaround ;) )

Funktioniert jetzt auch alles so, wie ich es geplant hatte :)
Danke für eure Hilfe!

Ich denke wenn ich es so am Dienstag meiner Lehrerin vorzeige wird sie zufrieden sein.
( Deswegen kommt auch leider kein anderer Algorithmus in Frage )

mfG
Benny