Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Sinus Funktion spinnt?! (https://www.delphipraxis.net/86257-sinus-funktion-spinnt.html)

Namenloser 11. Feb 2007 17:20


Sinus Funktion spinnt?!
 
Hallo,
ich habe ein eigenartiges problem...

**ARGH, ich weiß nciht, wie ichs erklären soll :/ Hier ein bisschen code:**

Delphi-Quellcode:
x := cos(richtung*pi/4) -> funzt
y := sin(richtung*pi/4) -> funzt nicht
"richtung" ist dabei ein wert zwischen 0 und 8, wobei ein einer-schritt für je 45° steht.

Bei cos kommt das richtige ergebnis raus, aber bei sin -5kommairgendwasE-20

Ich bin echt am verzweifeln, da ich keinen plan ahbe, woran das liegt :wall:

3_of_8 11. Feb 2007 17:22

Re: Sinus Funktion spinnt?!
 
Du sagst, es kommt "-5kommairgendwasE-20" raus. Da Gleitkommazahlen de facto nicht ganz genau sind, kann es gut sein, dass er damit 0 meint. Kommt das hin?

Namenloser 11. Feb 2007 17:27

Re: Sinus Funktion spinnt?!
 
Ja, das könnte sein, komischerweise kommt bei der Ausgabe als text aber -1 heraus o.O

Wie kann man das denn verhindern?


Übrigens wundert es mich, dass da steht -5.blaE-20, müsste es denn nicht 5.blaE+20 heißen?

edit: ja, ich hab es überprüft, es muss tatsächlich null sein (bei der cosinus-funktion passiert übrigens bei dem entgegengesetzten winkel das gleiche, wie ich soeben bemerkt habe)

MrSpock 11. Feb 2007 17:32

Re: Sinus Funktion spinnt?!
 
Hallo,

nein e+20 wäre ja 10 hoch 20 und das wäre ja ein bisschen viel. :mrgreen:

Damit der Wert so nicht angezeigt wird, kannst du ihn für die Ausgabe formatieren, z.B.:

Delphi-Quellcode:
Format('%8.2f', [sin(StrToFloat(Edit1.Text)*pi/4)])

3_of_8 11. Feb 2007 17:38

Re: Sinus Funktion spinnt?!
 
Na dann passt ja alles. ;)

Gleitkommawerte sind manchmal etwas... gewöhnungsbedürftig. Hier ein paar Beispiele:

0 ist nicht gleich 0:
Es gibt ein +0 und ein -0, die beide aus Berechnungen entstehen können. Beim Rechnen fällt das nicht weiter auf, bei der Textausgabe schon.
Manchmal schlägt die Genauigkeit zu und aus einer 0 wird ein irgendwas*10^-20 oder so

1/+0=+INFINITY
1/-0=-INFINITY
-1/+0=-INFINITY
-1/-0=+INFINITY

Also bei sowas nicht wundern. ;)

EDIT: Was soll denn an dem E-20 nicht stimmen?

Namenloser 11. Feb 2007 17:40

Re: Sinus Funktion spinnt?!
 
@mr.spock: ja, aber es ist ja -5...

3_of_8 11. Feb 2007 17:43

Re: Sinus Funktion spinnt?!
 
Also.

-5E-20 bedeutet -5*10^(-20)
5E20 bedeutet 5*10^20

Das erste ist -0.00000000000000000005 und das zweite 500000000000000000000.

Siehst du den Unterschied?

Namenloser 11. Feb 2007 17:46

Re: Sinus Funktion spinnt?!
 
Vielen Dank an alle, ich habe es jetzt so gelöst:

floattostrF(num,fffixed,15,7)

Aber eine Frage hätte ich noch: Durch das fffixed (vorher hatte ich ffgeneral, daran lags wohl (?)), werden dei ganzen überflüssigen nullen mit angezeigt. Gibt es eine Option, die "wegzumachen", oder muss ich das selber machen?

@3_of_8: ok, ich geb mich geschlagen^^ (Exponent hatten wir auch in der schule eigentlich noch nicht^^)

3_of_8 11. Feb 2007 17:50

Re: Sinus Funktion spinnt?!
 
Ja, mit ffGeneral. ;)

Namenloser 11. Feb 2007 17:53

Re: Sinus Funktion spinnt?!
 
Das hatte ich ja zuerst, da kamen ja exponenten raus :(

EDIT: ich hab mir jetzt diese kleine funktion geschrieben:

Delphi-Quellcode:
function erasezeros(s: string): string;
var i: integer;
    endpos: integer;
begin
  if pos('.',s) = 0 then
  begin
    result := s;
    exit;
  end;

  for i := length(s) downto pos('.',s) do
  begin
    if s[i] <> '0' then
    begin
      endpos := i;
      break;
    end;
  end;
  result := copy(s,1,endpos);
  if ansilastchar(result) = '.' then
    setlength(result,length(result)-1);
end;
Funktioniert, aber wenn jemand eine bessere lösung findet, darf er sie ruhig verraten :D

Klaus01 11. Feb 2007 18:52

Re: Sinus Funktion spinnt?!
 
Nun, wenn Du einen Wert auf 0 Prüfen willst,
kanst Du das mit isZero aus der Math Unit testen.

Hier ein Auszug aus der Hilfe:
Zitat:

Unit

Math
Category
Arithmetic routines

function IsZero(const A: Single; Epsilon: Single = 0): Boolean; overload;
function IsZero(const A: Double; Epsilon: Double = 0): Boolean; overload;
function IsZero(const A: Extended; Epsilon: Extended = 0): Boolean; overload;

Description
Use IsZero to test whether the value specified by AValue is zero, or differs from zero by at most Epsilon.
Grüße
Klaus

3_of_8 11. Feb 2007 18:57

Re: Sinus Funktion spinnt?!
 
Dabei sollte man erwähnen, dass Epsilon (in der Mathematik) eine reelle Zahl ist, die beliebig klein, aber größer als 0 ist. Soll also praktisch eine Art Wert sein, der "noch" als 0 gilt.

Du könntest übrigens versuchen, für Digits 0 oder 1 oder sowas anzugeben. Dann sollten die Nullen weg sein.

Hawkeye219 11. Feb 2007 19:35

Re: Sinus Funktion spinnt?!
 
Hallo,

vielleicht kannst du die Werte etwas vorbehandeln:

Delphi-Quellcode:
function Fuzzy (aValue: Double; aEpsilon: Double = 1E-9): Double;
begin
  if (Abs(aValue) < aEpsilon) then
    Result := 0.0
  else
    Result := aValue;
end;

begin
  Label1.Caption := Format('x: %.3g', [Fuzzy(x)]);
  Label2.Caption := Format('y: %.3g', [Fuzzy(y)]);
end;
Gruß Hawkeye

Namenloser 11. Feb 2007 20:27

Re: Sinus Funktion spinnt?!
 
Das sieht interessant aus, aber was macht das? :?:

Hawkeye219 11. Feb 2007 20:55

Re: Sinus Funktion spinnt?!
 
Die Funktion Fuzzy liefert für (absolut gesehen) sehr kleine Werte eine 0, alle anderen Werte werden unverändert zurückgegeben. Die Genauigkeit läßt sich optional über den Parameter aEpsilon vorgeben, der Defaultwert ist 1E-9.

Bei der Format-Funktion bewirkt die Angabe "%g" das, was FloatToStr mit dem Parameter ffGeneral erreicht - überflüssige Nullen am Ende werden abgeschnitten. In der Online-Hilfe von Delphi findest du eine genaue Beschreibung der Parameter unter dem Stichwort "SysUtils.Format Routine".

Gruß Hawkeye

swatch 19. Feb 2007 13:36

Re: Sinus Funktion spinnt?!
 
Könnte man anstatt der Funktion Fuzzy nicht auch die Funktion SimpleRoundTo aus der Unit Math verwenden? Diese würde auch für andere eventuelle, minimale Ungenauigkeiten einspringen.

(function SimpleRoundTo(const AValue: Double, const ADigit: TRoundToRange): Double;) //ADigit gibt die Rundungsgenauigkeit, also aEpsilon an


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:15 Uhr.

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