Seite 1 von 2

Sin/Cos/Tan mit Double Genauigkeit

Verfasst: 27.03.2009 13:34
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

Verfasst: 27.03.2009 13:40
von Kaeru Gaman
>> Ich weis das es unter Windows dafür schon Befehle gibt
:?: :?: :?:

... was hab ich da verpasst?

Verfasst: 27.03.2009 13:42
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:

Verfasst: 27.03.2009 13:45
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.

Verfasst: 27.03.2009 13:46
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...

Verfasst: 27.03.2009 13:51
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...

Verfasst: 27.03.2009 14:20
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

Verfasst: 27.03.2009 14:37
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) 

Verfasst: 27.03.2009 15:58
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.

Verfasst: 27.03.2009 16:27
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