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: Alles auswählen
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