Aktuelle Zeit: 07.04.2020 19:25

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: (math) Fast Sinus
BeitragVerfasst: 03.12.2005 03:02 
Offline

Registriert: 10.11.2004 03:22
dieses posting wurde inspiriert von einem detail in diesem thread:
http://forums.purebasic.com/german/viewtopic.php?t=5856


für viele sachen braucht man eine sinus funktion.

dass ein array schneller ist, wurde ja schon oft erwähnt.

dann taucht das problem auf, wie groß das array sein soll.

wenn das 360 felder groß ist, muss ich den winkel begrenzen.
ich müsste also ein Modulo einbauen,
und das eventuelle negative vorzeichen eliminieren...

aber

kann ich das auch anders begrenzen, ohne modulo?
muss ein vollkreis 360° haben?

wenn ich den vollkreis nicht in 360 schritte,
sondern in 1024, 2048 oder 4096 schritte einteile, also eine 2er-potenz,
dann kann ich den modulo mit bitweisem AND bestimmen,
und spare tonnen von rechenzyklen.


also

im folgenden beispiel wird ein sinus-array erstellt, mit 4096 feldern.
damit wird der vollkreis beschrieben 0°->360°

(jeder der bruchrechnung kann, weiß nun, das jeder schritt im array 360 4096stel grad weitergeht)

in Zeile 16 wird der winkel in "arc" umgerechnet, in den index

winkel ist also ein winkel in 0-360 grad, arc ein winkel mit 0-4096 grad.

(für eine anwendung würde ich allerdings empfehlen, gleich mit einem 4096-grad-vollkreis zu arbeiten)

den sinus eines beliebigen winkels hole ich jetzt mit SinA( arc & 4095)

das ist praktisch das modulo...

den cosinus hole ich aus derselben tabelle mit SinA( (arc + 1024) & 4095)
der cosinus ist schließlich ein 90° phasenverschobener sinus.

das plotten im fenster dient nur dem beweis, das die rechnung wirklich "dicht" ist,
also, das mittels des AND kein index außerhalb des arrays angesprochen wird.

das +15 bei der winkelerhöhung dient dazu, zu zeigen, dass es genau ist,
dass also immer auf 24tel kreisen geplottet wird.
bitte beliebig verändern...

hier nun das listing:
Code:
Dim SinA.f(4095)
#pi = 3.14159265

For n=0 To 4095
    SinA(n) = Sin(#pi / 2048 * n )      ; #pi als erstes, damit ein float übergeben wird
Next

winkel = 0

OpenWindow(0,0,0,800,600, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Sinustest")

Repeat
    StartDrawing(WindowOutput())

        arc = winkel * 4096 / 360                       ; umrechnung winkel -> index

        xp = 400 + SinA( arc & 4095 ) * 250             ; sinus aus dem array
        yp = 300 + SinA( (arc+1024) & 4095 ) * 250      ; cosinus ist 90° verschoben

        FrontColor(Random(255),Random(255),Random(255)) ; zufallsfarbe
        Circle(xp,yp,12+Random(12))                     ; kreis plotten, zufallsradius

        winkel +15                                      ; mal hier mit beliebigen werten spielen
        If winkel > 36000 : winkel = -36000 : EndIf    ; hundert vollkreise plus und minus

    StopDrawing()
   
    Delay(0)
    EVT = WindowEvent()

Until EVT = #PB_Event_CloseWindow


ich werde nen thread für rückfragen extra öffnen, ich hätte schon gerne feedback...

_________________
... machts gut und danke für den fisch ...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 17.12.2006 13:05 
Offline

Registriert: 14.09.2004 21:39
Also wenn man so Speed- und Speicher-bewusst sein will, dann braucht man doch nur 90° vorberechnen. Schlussendlich muss man diese XY-Koordinaten - je nach dem in welchem Quadranten der Winkel liegt - nur noch auf -/+ setzen.

So spart man sich noch mehr Speicher, hat gleiche (oder noch mehr) Genauigkeit. Nur der Speed ist wohl ein bisserl geringer.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 17.12.2006 13:15 
Offline

Registriert: 10.11.2004 03:22
das ist richtig.

ich habe deshalb ein 360°-Array verwendet, damit man so wenig wie möglich umrechnen muss.

der speicherverbrauch fällt meines erachtens nach nicht schwer ins gewicht.

ein Array mit Double und 131.072 Werten braucht grad mal ein einziges MB.
Peanuts!

(btw: es mag auffallen, das obiger code V3.94 ist)

_________________
... machts gut und danke für den fisch ...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 26.03.2007 15:14 
Offline

Registriert: 26.03.2007 15:05
Kaeru,

herzlichen Dank für diese Code! Anbei die 4.0 Anpassungen:

Code:
; PB 3.x code by Kaeru Gaman - adapted to PB4.x

Dim SinA.f(4095)

For n=0 To 4095
    SinA(n) = Sin(#PI / 2048 * n )      ; #pi als erstes, damit ein float übergeben wird
Next

winkel = 0

OpenWindow(0,0,0,800,600,  "Sinustest", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)

Repeat
   StartDrawing(WindowOutput(0))
      arc = winkel * 4096 / 360                            ; umrechnung winkel -> index
      xp = 400 + SinA( arc & 4095 ) * 250                  ; sinus aus dem array
      yp = 300 + SinA( (arc+1024) & 4095 ) * 250           ; cosinus ist 90° verschoben
      FrontColor(RGB(Random(255),Random(255),Random(255))) ; zufallsfarbe
      Circle(xp,yp,12+Random(12))                          ; kreis plotten, zufallsradius
      winkel +15                                           ; mal hier mit beliebigen werten spielen
      If winkel > 36000 : winkel = -36000 : EndIf          ; hundert vollkreise plus und minus
   StopDrawing()
   Delay(0)
   EVT = WindowEvent()
Until EVT = #PB_Event_CloseWindow

_________________
Grüße,
dell_jockey
_______________
Forex Trading Ideas


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 26.03.2007 15:31 
Offline

Registriert: 10.11.2004 03:22
freut mich, dass er dir nützt.
danke für die anpassung. :D

_________________
... machts gut und danke für den fisch ...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 23.02.2008 17:47 
Offline

Registriert: 26.03.2007 15:05
um dieses Thema erneut aufzuwärmen: für eine Anwendung habe ich das ganze ein bisl umgeschrieben und möchte das jetzt hier präsentieren:

Code:
; ---------------------------------------------------
;              SIN-COS-tables.pbi
; ---------------------------------------------------
; precomputed global SIN/COS lookup tables are
; referenced by macros to reduce function call
; overhead and avoid trig conversion calculations
; - fSIN ( degrees )    ; fast sine
; - fCOS ( degrees )    ; fast cosine
; ---------------------------------------------------
; based on Kaeru Gaman's following PureBoard entry:
; http://www.purebasic.fr/german/viewtopic.php?t=5884
; ---------------------------------------------------

Global _Trig_Resolution_.w = 16384   ; steps around unity circle, needs
                                     ; to be a power of 2, i.e.
                                     ; 512, 1024, 2048, 4096, 8192, ...
                                     ; the larger this value, the larger
                                     ; the tables become, but one also
                                     ; gets more precision
                                     
Global _Resolution_minus_One_.w = _Trig_Resolution_.w - 1                                     

Global Dim SinTable.f(_Resolution_minus_One_.w)
Global Dim CosTable.f(_Resolution_minus_One_.w)

Global Angle_to_Index.f = ( _Trig_Resolution_ / 360.0 )

_Trig_Res_halved_.w = _Trig_Resolution_.w >> 1              ; populate tables
For n = 0 To _Resolution_minus_One_.w                       
    SinTable(n) = Sin( (#PI / _Trig_Res_halved_.w) * n )
    CosTable(n) = Cos( (#PI / _Trig_Res_halved_.w) * n )
Next

Macro fSIN( degrees )
  SinTable( Int((Angle_to_Index.f * degrees) + 0.5 ) & (_Resolution_minus_One_.w) )
EndMacro

Macro fCOS( degrees )
  CosTable( Int((Angle_to_Index.f * degrees) + 0.5 ) & (_Resolution_minus_One_.w) )
EndMacro


; ------------------------------------------
; Usage
; ------------------------------------------
; set __UsageDefined__ to #True to test this
; file standalone
; ------------------------------------------
Define.b __UsageDefined__ = #True 
If __UsageDefined__
  For i = 0 To 359 Step 15
    Debug( "SIN(" + Str(i)+") = " + StrD( fSIN( i ), 6) )
    Debug( "COS(" + Str(i)+") = " + StrD( fCOS( i ), 6) )
  Next
EndIf

_________________
Grüße,
dell_jockey
_______________
Forex Trading Ideas


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 06.06.2008 00:42 
Offline

Registriert: 10.11.2004 03:22
war im Februar nicht da, sehe deinen Code jetzt erst per Zufall...

danke für deine Arbeit, sieht gut aus. :allright:

auch wenn die meilenlangen Underscores nicht mein Fall sind,
es ist dadurch tatsächlich allcompatibler...

_________________
... machts gut und danke für den fisch ...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: 06.06.2008 21:29 
Offline
Ein Admin
Benutzeravatar

Registriert: 29.08.2004 20:20
Wohnort: Saarbrücken
Ich würde allerdings keine Words, sondern Longs vorziehen, weil die schnell
sind.

_________________
Ubuntu Gnome 19.04 LTS x64, PureBasic 5.71 x64 (außerdem 4.41, 4.50, 4.61, 5.00, 5.10, 5.11, 5.21, 5.22, 5.30, 5.31, 5.40, 5.50, 5.60)
"Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen – Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen."


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye