Sin/Cos/Tan mit Double Genauigkeit

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Sin/Cos/Tan mit Double Genauigkeit

Beitrag von cxAlex »

Servus.

Nachdem PB Winkelfunktionen nur mit Float - Genauigkeit beherrscht hab ich mir Sinus, Cosinus und Tangens mal komplett selbst in Double - Genauigkeit programmiert. Ich weis das es unter Windows dafür schon Befehle gibt, aber es ging mir ums Ausprobieren und außerdem ist der Source so Cross Plattform fähig.

Hier der Code, viel Spaß damit :D :

Code: Alles auswählen

; Fakultät
Procedure.d _Fac(n)
  Protected tDouble.d = 1
  For i = 2 To n
    tDouble*i
  Next
  ProcedureReturn tDouble
EndProcedure

; Ohne 0 - Regel und nur für ganze Zahlen
Procedure.d _PowD(Num.d, Exp)
  Static i, oldNum.d 
  oldNum = Num
  Exp-1
  For i = 1 To Exp
    Num*oldNum
  Next
  ProcedureReturn Num
EndProcedure

; Sinus mit Double - Genauigkeit
Procedure.d SinD(rad.d)
  Static negate, rtvar.d, lrtvar.d, exp, i
  negate = -1
  rtvar = rad
  i = 1
  Repeat
    exp = i*2 + 1
    rtvar + (((_PowD(rad, exp))/_Fac(exp))*negate)
    If lrtvar = rtvar
      Break
    EndIf
    lrtvar = rtvar
    negate*-1
    i+1
  ForEver
  ProcedureReturn rtvar
EndProcedure

; Cosinus mit Double - Genauigkeit
Procedure.d CosD(rad.d)
  ProcedureReturn SinD(rad.d+1.5707963267948966)
EndProcedure

; Tangens mit Double - Genauigkeit
Procedure.d TanD(rad.d)
  ProcedureReturn SinD(rad)/CosD(rad)
EndProcedure

Macro Demo_SF(Angel)

Debug "-----------------------------------------"
Debug "Sinus: "
Debug "PB: "
Debug Sin(Angel)
Debug "Double: "
Debug SinD(Angel)
Debug "-----------------------------------------"

Debug "-----------------------------------------"
Debug "Cosinus: "
Debug "PB: "
Debug Cos(Angel)
Debug "Double: "
Debug CosD(Angel)
Debug "-----------------------------------------"

Debug "-----------------------------------------"
Debug "Tangens: "
Debug "PB: "
Debug Tan(Angel)
Debug "Double: "
Debug TanD(Angel)
Debug "-----------------------------------------"
EndMacro

Demo_SF(9.8765432109876)
Gruß, Alex
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

>> Ich weis das es unter Windows dafür schon Befehle gibt
:?: :?: :?:

... was hab ich da verpasst?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

cxAlex hat geschrieben:Ich weis das es unter Windows dafür schon Befehle gibt
1. Windowsspezifisch gibt es dafür garantiert keine Befehle
2. Das was du meinst ist Assemblercode und das geht unter allen x86 dann.

[EDIT]

P.S.: Angel :freak:
Zuletzt geändert von DarkDragon am 27.03.2009 15:25, insgesamt 1-mal geändert.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Ich weis das ich in dem Forum schon mal ne API oder zumindest nen Import von Winkelfunktionen mit Double-Genauigkeit gesehen hab, finds nur grad nicht. Und mit Cross Plattform mein ich das ich keine Windows - API verwende, und der Source sollte auch auf nem PPC laufen wenn du ihn darauf kompilierst.
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

DarkDragon hat geschrieben:1. Windowsspezifisch gibt es dafür garantiert keine Befehle
Vielleicht die Funktionen aus der MSVCRT die man auch in PB verwenden kann...
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

milan1612 hat geschrieben: Vielleicht die Funktionen aus der MSVCRT die man auch in PB verwenden kann...
Ja, MSVCRT wars. Konnte mich nur nicht an den Namen erinnern...
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7032
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

Da hat wohl einer was von Taylorreihen gehört ...

das problem bei deinen Funktionen ist nur, das dein entwicklungspunkt immer bei 0,0 ist
Damit sind deine Funktionen immer nur in dieser Umgebung sehr genau...
sobald du größere Winkel einsetzt 10*#pi, 15*#pi werden die werde immer ungenauer bin hin zu 20*#pi wo der overflow kommt ...

Code: Alles auswählen

Macro Demo_SF(n, Angel) 
Debug Str(n)+" : "+StrF(Cos(Angel))+" <> "+StrD(CosD(Angel))
EndMacro 
For n = 1 To 20
Demo_SF(n, #PI*n)
Next
du solltest also auf jedenfall noch sicher stellen das die Werte immer innerhalb von -2pi +2pi liegen, also zB mit :

Code: Alles auswählen

 ; Modulo F
 Macro Mod(Value, Factor)
  ( (Value)-Int((Value)/(Factor))*(Factor) )
 EndMacro
dann macht Mod(Angle, (2*#pi))
aus 27#pi halt wieder 1#pi
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Danke Stargate.

Hab dein Modulo jetzt eingebaut, jetzt bleiben die Winkel zwischen +-2*PI, damit sollte die Genauigkeit immer sehr hoch sein.

Code: Alles auswählen

Macro _Mod(Value, Factor)
  ( (Value)-Int((Value)/(Factor))*(Factor) )
EndMacro

; Fakultät
Procedure.d _Fac(n)
  Protected tDouble.d = 1
  For i = 2 To n
    tDouble*i
  Next
  ProcedureReturn tDouble
EndProcedure

; Ohne 0 - Regel und nur für ganze Zahlen
Procedure.d _PowD(Num.d, Exp)
  Static i, oldNum.d
  oldNum = Num
  Exp-1
  For i = 1 To Exp
    Num*oldNum
  Next
  ProcedureReturn Num
EndProcedure

; Sinus mit Double - Genauigkeit
Procedure.d SinD(rad.d)
  Static negate, rtvar.d, lrtvar.d, exp, i
  negate = -1
  rad = _Mod(rad, 6.2831853071795862)
  rtvar = rad
  i = 1
  Repeat
    exp = i*2 + 1
    rtvar + (((_PowD(rad, exp))/_Fac(exp))*negate)
    If lrtvar = rtvar
      Break
    EndIf
    lrtvar = rtvar
    negate*-1
    i + 1
  ForEver
  ProcedureReturn rtvar
EndProcedure

; Cosinus mit Double - Genauigkeit
Procedure.d CosD(rad.d)
  ProcedureReturn SinD(rad.d + 1.5707963267948966)
EndProcedure

; Tangens mit Double - Genauigkeit
Procedure.d TanD(rad.d)
  ProcedureReturn SinD(rad)/CosD(rad)
EndProcedure

Macro Demo_SF(Angle)
  
  Debug "-----------------------------------------"
  Debug "Sinus: "
  Debug "PB: "
  Debug Sin(Angle)
  Debug "Double: "
  Debug SinD(Angle)
  Debug "-----------------------------------------"
  
  Debug "-----------------------------------------"
  Debug "Cosinus: "
  Debug "PB: "
  Debug Cos(Angle)
  Debug "Double: "
  Debug CosD(Angle)
  Debug "-----------------------------------------"
  
  Debug "-----------------------------------------"
  Debug "Tangens: "
  Debug "PB: "
  Debug Tan(Angle)
  Debug "Double: "
  Debug TanD(Angle)
  Debug "-----------------------------------------"
EndMacro

Demo_SF(-9.8765432109876) 
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
Josef Sniatecki
Beiträge: 657
Registriert: 02.06.2008 21:29
Kontaktdaten:

Beitrag von Josef Sniatecki »

Nun bleibt aber die Frage wie man für "PowD" einen Exponent als Double
ermöglichen kann. Immerhin möchte man nicht nur genau Potenzieren
sondern auch Radizieren. Für die Wurzel könnte man dann "PowD(x,0.5)"
schreiben.

Nur so am Rande, weil es ja eigentlich um die Winkelfunktionen geht.
PB 4.61 | Windows Vista - 32Bit
Homepage

"Wahrlich es ist nicht das Wissen, sondern das Lernen, nicht das Besitzen sondern das Erwerben, nicht das Dasein, sondern das Hinkommen, was den grössten Genuss gewährt." - Carl Friedrich Gauß
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Und wieso soll PB in einer halbwegs aktuellen Version die Winkelfunktionen nicht mit Double-Precision ausspucken :shock:?
Für Reihenentwicklungen habe ich hier übrigens mal einen Big-Calculator zum Besten gegeben :mrgreen:.

Gruß
Helle
Antworten