AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

tan() von Single, Double, etc.

Ein Thema von Rollo62 · begonnen am 20. Nov 2017 · letzter Beitrag vom 22. Nov 2017
Antwort Antwort
Seite 1 von 2  1 2      
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.062 Beiträge
 
Delphi 10.4 Sydney
 
#1

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 12:14
Reicht es nicht, wenn du das Tan-Ergebnis auf größer 1 und kleiner minus 1 prüfst?
Warum sollte tan(60°) = sqrt(3) = 1.732... ungültig sein?
Stimmt, ich hätte nicht nur mit den paar Werten mit vielfachen von 45 testen sollen.

Delphi-Quellcode:
program Project3;

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.SysUtils, System.Math,
  Types;

procedure Main;
var
  I: Integer;
  Degree, Rad, TanResult: Single;
  LogMsg: string;
  DegArray: TArray<Integer>;
begin
  for I := 0 to 360 do
  begin
    Degree := I;
    Rad := DegToRad(Degree);
    TanResult := Tan(Rad);
    if InRange(TanResult, -1000, 1000) then
    begin
      LogMsg := Format('Grad: %3.d - Rad: %2.4f - Tan: %2.4f', [I, Rad, TanResult]);
    end
    else
      LogMsg := Format('Ungültige Eingabe für Tan(%3.d) - Rad: %2.4f - Tan: %2.4f', [I, Rad, TanResult]) ;

    Writeln(LogMsg);
  end;
end;

begin
  try
    Main;
    Readln
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.
Die Grenze mit 1000 ist natürlich willkürlich. Muss man je nach gewünschter Genauigkeit anpassen.
Der Windows-Taschenrechner liefert bspw. für tan(90.001°) = -57295,7795...
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.932 Beiträge
 
Delphi 12 Athens
 
#2

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 13:06
@Namenloser

Zitat:
Dem muss man sich als Aufrufer einfach bewusst sein.
Ja, genau dehalb bezeiche ich als "Bug", denn das genaue Verhalten ist ja nicht dokumentiert und bei Single, Double, etc. auch individuell anders.
Wie du schon sagts, es würde auch das Epsilon fehlen, das muss sich selbst der Aufrufer noch erraten (oder ertesten).

In der Praxis lege ich auch ein Epsilon fest, und selbst dabei kommt man in logische Probleme.
Habe nämlich gerade des Epsilon von 1 nano auf 1 micro hochgesetzt, und selbst das ist bei bestimmten Werten
nicht genug wenn man z.B. millimeter pro meter braucht können große Aubweichungen Auftreten.

Deshalb ist der Vorschlag von TiGü ja interessant, weil ich den Bereich nicht im Eingang sondern im Ausgang festlegen kann.

@gammatester

Zitat:
Für Single/Double wird tan(DegToRag(x)) nie eine Exception werfen
Das mag sein, mir geht es aber um die Richtigkeit der Ergebnisse.
Wahrscheinelich wäre eine Exception sogar sinnvoller als falsche Werte.


Das Ganze hat für mich den Geschmack von "irgendeinen Tod muss man sterben".


Rollo
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 13:23
Ja, genau dehalb bezeiche ich als "Bug", denn das genaue Verhalten ist ja nicht dokumentiert und bei Single, Double, etc. auch individuell anders.
Genau genommen ist es eigentlich eine wohlbekannte und zwangsweise Folge des Rechnens mit Zahlendarstellungen nach IEEE 754. Braucht man höhere Genauigkeit als diese zusichern, muss man zu entsprechenden Libs greifen die diese Eigenschaften umschiffen.

Zitat:
Das mag sein, mir geht es aber um die Richtigkeit der Ergebnisse.
Nochmal: Die Ergebnisse sind richtig. Die Eingabe in Grad und die Nutzung von binärer Gleitkommaarithmetik verschleiern lediglich die Rundungen die auf dem Weg zum Ergebnis hin notwendigerweise passieren. Wie schon erwähnt wirst du genau genommen (und darum geht es dir ja) es niemals schaffen der tan() Funktion einen Parameter zu übergeben der korrekterweise zu NaN führt, da eben genau diese Parameter schon per Definition eine Wertigkeit haben, die kein x86 Computer der Welt (nativ) korrekt abbilden kann.

Zitat:
Das Ganze hat für mich den Geschmack von "irgendeinen Tod muss man sterben".
Das ist schon durch die Nutzung von binären Gleitkommazahlen abgemachte Sache.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#4

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 14:39
Das mit nachträglichen Korrektur ist doch Bastelei, und jemandem, dem es auf Genauigkeit ankommt, unwürdig. Selbst bei einem Bereich von -1000..1000 wäre dann tan(89.95°) ungültig. Und ich würde mit Recht darauf hinweisen, daß das ein Bug ist.

Wie gesagt, die Gleitkomma-Arithmetik ist exakt, genau so exakt wie Integer-Arithmetik. Sorgen mach mir der schlampige Umgang von EMBA z.B. mit der Bereichsreduktion für sin, cos etc. Für Beispiele im Vergleich zu DAmath siehe unten. Und selbstverständlich kann man die Polstellen für tan bei 90° + k * 180° sauber darstellen, die Funktion tand in DAMath liefert allerdings Infinity statt NaN.
Code:
(Machine eps for double = 2.220446049250E-016)
-----------------------------------------------------------------
Test of DAMath.cos
at 10000 random values in [-10.0000000000 .. 10.0000000000]
RMS = 0.25, max rel = 0.91 eps at
 x(dbl) =    -8.11413601040840E+000 = $C0203A7009000000
 y(dbl) =    -2.57229736666779E-001 = $BFD07673B6A2B86F
 y(mpf) = -2.57229736666778837208918104020787799191734279958E-1

Test of DAMath.cos
at 10000 random values in [0.0000000000 .. 1000000000.0000000000]
RMS = 0.24, max rel = 0.90 eps at
 x(dbl) =     3.09463918209076E+008 = $41B2720B6E358600
 y(dbl) =    -2.58174239840314E-001 = $BFD085ED3F3229E9
 y(mpf) = -2.58174239840313841975953009564740744055663588700E-1

Test of DAMath.cos
at 10000 random values in [1000000000.0000000000 .. 5.000000000000E+018]
RMS = 0.24, max rel = 0.88 eps at
 x(dbl) =     6.18510209900251E+017 = $43A12AC7848E1D0B
 y(dbl) =     2.60040880178592E-001 = $3FD0A48280FF5DF3
 y(mpf) = +2.60040880178592397382630269801769340226378199265E-1

Test of system.cos
at 10000 random values in [-10.0000000000 .. 10.0000000000]
RMS = 0.19, max rel = 0.55 eps at
 x(dbl) =     7.85423278808594E+000 = $401F6ABC00000000
 y(dbl) =    -2.51154108814005E-004 = $BF3075AAAF01351D
 y(mpf) = -2.51154108814004449238616298892359426342137631612E-4

Test of system.cos
at 10000 random values in [0.0000000000 .. 1000000000.0000000000]
RMS = 257703.83, max rel = 14362143.15 eps at
 x(dbl) =     7.73584246635437E+008 = $41C70DFABB515600
 y(dbl) =     3.12296110038815E-004 = $3F347775944C00FF
 y(mpf) = +3.12296109042891252641009359676336492980461957722E-4

Test of system.cos
at 10000 random values in [1000000000.0000000000 .. 5.000000000000E+018]
RMS = 931290736633651.00, max rel = 60109746020807300.00 eps at
 x(dbl) =     2.46350079825587E+018 = $43C1180E763FF750
 y(dbl) =     2.93392152252295E-003 = $3F6808E11F9FE142
 y(mpf) = -2.37621355417792405078768037054894663841091297810E-4
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#5

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 17:55
daß das ein Bug ist.
Dann ist es ein Bug in jeder x86/x64 CPU der Welt. Denn Delphi macht nichts anderes als deren integrierten trigonometrischen Funktionen ohne viel drumrum direkt zu nutzen. In meinen Augen KEIN Bug, sondern eine systembedingte, bekannte Designschwäche, mit der ALLE Compiler entweder leben müssen, und/oder für gehobene Ansprüche Libs einsetzen, die die Spezialfälle gezielt abdecken.

Und NEIN, du kannst 90° usw. niemals 100%ig korrekt darstellen, es sei denn du hast unendlich breite Register, ooooder eben eine Lib die bei entsprechenden Parametern gesondert vorgeht, und/oder andere Algorithmen verwendet, die sich nicht auf die integrierten Funktionen der CPU verlassen. (Die sind dann natürlich etwas langsamer in aller Regel.)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#6

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 18:49
Lies noch einmal genau nach! Ich habe beschrieben:
Das mit nachträglichen Korrektur ist doch Bastelei, und jemandem, dem es auf Genauigkeit ankommt, unwürdig. Selbst bei einem Bereich von -1000..1000 wäre dann tan(89.95°) ungültig. Und ich würde mit Recht darauf hinweisen, daß das ein Bug ist.
Und wenn tan(89.95°)=Nan oder Inf oder was auch immer Du als ungültig wählst, kein Bug wäre, was ist dann noch ein Bug?
Und NEIN, du kannst 90° usw. niemals 100%ig korrekt darstellen, es sei denn du hast unendlich breite Register, ooooder eben eine Lib die bei entsprechenden Parametern gesondert vorgeht, und/oder andere Algorithmen verwendet, die sich nicht auf die integrierten Funktionen der CPU verlassen.
Das ist doch Unsinn, selbstverständlich kann 90 exakt als Double/Single darstellen, und man braucht auch keine 'unendlich breite' Register, um korrekt gerundete Werte für sin, tan etc auszurechnen. Man muß es nur wollen! Für ein frei zugängliches Beispiel zu nennen siehe http://cvsweb.openbsd.org/cgi-bin/cv.../lib/libm/src/, und nicht wie EMBA, das Problem aussitzen. Immerhin haben sie in der 64-Bit-RTL einen Schritt in die richtige Richtung gemacht und eine schon 37 Jahre junge Technik von Cody/Waite übernommen, aber den letzten Schritt woll(t)en sie nicht gehen, aus welchen Gründen auch immer (zumindest im letzten für mich vorliegen Quellcode of Delphi18/XE4).
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.048 Beiträge
 
Delphi 12 Athens
 
#7

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 21:28
Das ist doch Unsinn, selbstverständlich kann 90 exakt als Double/Single darstellen,
Dummerweise nimmt die Funktion aber keine Grad an sondern Radians. Daher werden die 90° mit einer nur begrenzt genauen Repräsentation von π multipliziert, was dann im Ergebnis eben nicht genau π/2 entspricht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.062 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 15:12
Das Ganze hat für mich den Geschmack von "irgendeinen Tod muss man sterben".
Die Frage ist halt auch, wie genau man es braucht? Und wofür wird es gebraucht?
Für komplexe mathematische Geschichten würde ich auf eine externe Bibliothek setzen.
Ob man wirklich den tan-Wert für bspw. 89.9999° braucht sei mal dahingestellt.
Die Genauigkeit, bis wann man welche Eingangswerte behandelt muss man sich vorher überlegen.
Was für Werte hast du denn? Willst du irgendwas darstellen?

Delphi-Quellcode:
const
  FAKTOR = 10000;

procedure Main;
var
  I: Integer;
  Degree, Rad, TanResult: Double;
  LogMsg: string;
  DegArray: TArray<Integer>;
begin
  for I := 89 * FAKTOR to 90 * FAKTOR do
  begin
    Degree := I / FAKTOR;
    Rad := DegToRad(Degree);
    TanResult := Tan(Rad);
    LogMsg := '';
    if InRange(TanResult, -500000, 500000) then
    begin
      LogMsg := Format('Grad: %2.4f - Tan: %2.4f', [Degree, TanResult]);
    end
    else
      LogMsg := Format('Ungültige Eingabe für Tan(%2.4f) - Tan: %2.4f', [Degree, TanResult]) ;

    if LogMsg <> 'then
      Writeln(LogMsg);
  end;
end;
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
1.018 Beiträge
 
Delphi 2009 Professional
 
#9

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 17:29
@gammatester: Ich verwende derzeit in meiner SVG-Unit die trigonometrischen Funktionen von Delphi. Genutzt werden ausschließlich Extended-Werte. Die Genauigkeit überzeugt mich nicht. Verbessert AMath (nicht DAMath) desselben Autors diese Genauigkeit merklich?
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
gammatester

Registriert seit: 6. Dez 2005
999 Beiträge
 
#10

AW: tan() von Single, Double, etc.

  Alt 20. Nov 2017, 18:59
@gammatester: Ich verwende derzeit in meiner SVG-Unit die trigonometrischen Funktionen von Delphi. Genutzt werden ausschließlich Extended-Werte. Die Genauigkeit überzeugt mich nicht. Verbessert AMath (nicht DAMath) desselben Autors diese Genauigkeit merklich?
Ja, und wenn Du Fragen hast, stehe ich selbstverständlich zur Verfügung. Bei den trigonometrischen extended Funktionen kommt erschwerend hinzu, daß ein viel größerer Bereich bis 2^16384 behandelt werden muss und die Reduktion mod 2*Pi entsprechend aufwendig ist. Für Vergleiche siehe die Datei t_amathx.cmp im Archiv http://www.wolfgang-ehrhardt.de/amath_2017-11-02.zip.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:59 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