Avatar billede cms Nybegynder
24. september 2001 - 16:01 Der er 29 kommentarer og
1 løsning

Sinus calculation

Nogen der kan give mig en opskrift på hvordan min lommeregner og computer udregner sin(x)
Avatar billede ziron Nybegynder
24. september 2001 - 16:03 #1
brug funktionen sin under math

og så for at regne det om til grader bag efter radtogrd eller sådan noget lingende, har ikke lige delphi på mig...

/ZIRON
Avatar billede snowball Novice
24. september 2001 - 16:07 #2
Nedenstående er et eksempel der bruger både sinus og cosinus !

function Rotate2D(p:TPoint; alpha:double): TPoint;
var
  sinus, cosinus : Extended;
begin
(*
  sinus  := sin(alpha);
  cosinus := cos(alpha);
*)
  { twice as fast than calc sin() and cos() }
  SinCos(alpha, sinus, cosinus);

  result.x := Round(p.x*cosinus + p.y*sinus);
  result.y := Round(-p.x*sinus + p.y*cosinus);
end;


Snowball
Avatar billede cms Nybegynder
24. september 2001 - 16:07 #3
Det er ikke det jeg vil. Jeg vil rent matematisk og dermed også programmeringsmæssigt vide - hvad ligger der i den funktion (og jeg ved godt at delphi bare kalder processorens funktion FSINCOS eller sådannogetlignende)
Jeg ville have noget i retning af

function MinSinusFunktion(X: Extended): Extended;
begin
  Result := Sqrt(X*X-1)/2*sqrt((x+1)*pi);
end;

(Bare et underligt eksempel)
Avatar billede pellelil Nybegynder
24. september 2001 - 16:09 #4
Du skal være klar over at Delphi arbejder i Radianer (hvor din lommeregner sikker arbejder i grader). Hvis du således skal udregne Sin(45°) så skal du først omregne de 45° til radianer:

Result := Sin(DegToRad(45));
Avatar billede ziron Nybegynder
24. september 2001 - 16:09 #5
arrr okay, hvad er sinus altså...

hmm så skal man jo tal at lege matematik lærer, øv bøv...

/ZIRON
Avatar billede cms Nybegynder
24. september 2001 - 16:10 #6
Jeg kender godt forskel på grader/radianer :-)

Sagt på en anden måde: Jeg vil bare gerne vide, hvad det matematiske forhold er mellem y og x i y=sin(x)
Avatar billede martinlind Nybegynder
24. september 2001 - 16:15 #7
Avatar billede nca Juniormester
24. september 2001 - 16:22 #8
Tegn et koordinatsystem
Lad x-aksen være det ene ben i din vinkel
Afsæt den ønskede vinkel med toppunkt i (0,0)
Lav en cirkel med radius 1 og centrum i (0,0)
Vinklens venstre ben skærer cirklen i (cos(x),sin(x))
Avatar billede cms Nybegynder
24. september 2001 - 16:23 #9
har du lige umiddelbart et forslag til hvordan jeg skal tegne vinklen (100% nøjagtigt), og dermed hvordan jeg så kan beregne (cos(x),sin(x)) ?
Avatar billede cms Nybegynder
24. september 2001 - 16:27 #10
Indtil hvad jeg ved nu skal jeg bruge sinus og cosinus-funktionerne til at tegne vinklen, og så ryger lidt af fidusen jo :-)
Avatar billede cms Nybegynder
24. september 2001 - 16:31 #11
Martin> Meget interessant side. Jeg kan dog ikke finde noget om sinus, der er relevant. Det eneste jeg kan finde handler om beregning af komplex sinus udfra sinus (hvad det så end er)
Avatar billede pellelil Nybegynder
24. september 2001 - 16:59 #12
var
  Centrum: TPoint;
  Radius: Integer;
  Punkt: TPoint;
begin
  // Centrum := ???
  // Radius := ???
  for I := 0 to 360 do begin
    Punkt.X := (Cos(DegToRad(I)) * Radius) + Centrum.X;
    Punkt.Y := (Sin(DegToRad(I)) * Radius) + Centrum.Y;
    //TegnDinePunkter
  end;
end;
Avatar billede cms Nybegynder
24. september 2001 - 17:03 #13
Pellelil> Well, jeg kan godt finde ud af at beregne punkter med sinus og cosinus *g* - jeg ville bare gerne \'bag om\' sinus-funktionen itself.
Avatar billede pellelil Nybegynder
24. september 2001 - 17:13 #14
Vil du se hvordan Borland har programmer Sin/Cos?
Avatar billede cms Nybegynder
25. september 2001 - 18:47 #15
De kalder jo bare en funktion i compileren. Jeg skal bruge princippet bag - læs i øvrigt ovenfor.

Jeg kan fortælle, jeg selv har eksperimenteret lidt. Jeg har på en TI-83 leget lidt med at finde koordinaterne til en andengradsfunktion/parabel, der skulle ligge med toppunkt i (.5; 1) og skære punktet (0; 0) og (1; 1). Hvis man kigger på en  halv bølgelængde fra en sinuskurve, udgør den en parabel (right?).
Det gav funktionen y = -4x^2 +4x, som rammer disse punkter men ellers er noget upræcis. Det kan jeg se ved at lægge y = sin(x*pi) ind oveni.

Jeg har derfor idag lagt flere punkter ind, som geometrisk beviseligt skal være en del af kurven.
Det drejer sig om: sin(pi/4)=sqrt(2)/2 altså (.25; sqrt(2)/2) i ovenstående, og den modsatte - (.75; sqrt(2)/2).
Jeg er i øjeblikket i gang med at reducere på formlen, så den kommer til at passe (håber det er muligt).

Avatar billede cms Nybegynder
25. september 2001 - 18:48 #16
\'funktion i compileren\' skulle have været \'en funktion i cpu-en\'
Avatar billede cms Nybegynder
25. september 2001 - 20:06 #17
Og så fik jeg forkortet ligningerne. Det kan ikke være en parabel :-(, da alle betingelser så ikke bliver opfyldt...
funktionen: f(x) = -4xx + 4x
opfylder: (0;0) (.5;1) (1;0)
funktionen: f(x) = -8/3*sqrt(2)*X*X + 8/3*sqrt(2)*x
opfylder: (0;0) (.25; sqrt(2)/2) (.75; sqrt(2)/2) (1;0)

Det kan ikke lade sig gøre (har jeg bevist på mit papir) at bruge f(x) = axx + bx + c til denne opgave :-(
Avatar billede abx Nybegynder
25. september 2001 - 23:34 #18
CMS Skrev
\"Jeg kan fortælle, jeg selv har eksperimenteret lidt. Jeg har på en TI-83 leget lidt med at finde koordinaterne til en andengradsfunktion/parabel, der skulle ligge med toppunkt i (.5; 1) og skære punktet (0; 0) og (1; 1). Hvis man kigger på en  halv bølgelængde fra en sinuskurve, udgør den en parabel (right?)...\"

Nej! Det er ikke en parabel. Men det ligner godt
og er måske endda brugbart i praksis!

For at besvare dit oprindelige spørgsmål:

Det afhænger af din lommeregners fabrikat!
Hvert fabrikat har sin implementering. Det gælder også for PC\'ere på hardware niveau. 80287 havde
ikke en SIN funktion indbygget. Men 80387, 486, Pentium etc. har. Det er en forretningshemlighed hvordan den er kodet! Spørg selv Intel.

Der findes en algoritme, der kaldes Cordic- algoritmen. Du kan søge efter denne på nettet og få masser af uddybende svar.

En anden mulighed som ofte benyttes:
Brug en såkaldt Taylorudvikling. Det kan ikke forklares kort hvad det er andet end at det er det bedst mulige n\'te grads polynomium

F.eks er SIN(x) cirka lig med

x - x^3/(3*2) +x^5/(5*4*3*2) - x^7/(7*6*5*4*3*2)+... (saa langt du orker)







Avatar billede abx Nybegynder
25. september 2001 - 23:36 #19
(Det må du da æde som svar! :-) )
Avatar billede borrisholt Novice
26. september 2001 - 12:20 #20
MHT hvad Delphi kalder og ikke kalder så er det ikke noget at diskutere .. I System.pas finder man implementationen af sinus funktionen :

procedure      _SIN;
asm
        FSIN
        FNSTSW  AX
        SAHF
        JP      @@outOfRange
        RET
@@outOfRange:
        FSTP    st(0)  { for now, return 0. result would      }
        FLDZ            { have little significance anyway      }
end;


Den opmærksomme læser vi straks bemærke dels at sinus(x) er direkte understøtter i Assembler samt at funkrionen er erklæret som en procedure. Sidstnævnte laver compileren ompå når man kompilerer System.pas

JEns B
Avatar billede pellelil Nybegynder
26. september 2001 - 12:36 #21
abx\'s svar lyder meget i stil med hvad jeg (i sin tid) lærte, og man ser jo straks at Sin/Cos ikke ligefrem er de mest \"tilgængelige routiner\". Man kan ofte med fordel i et programs opstart opbygge en tabel med disse værdier og så blot bruge disse i programmet (i stedet for at beregne dem flere gange).
Avatar billede borrisholt Novice
26. september 2001 - 13:54 #22
DVS med andere ord så vil du gerne have plotter f(x) = -4xx + 4x
ind på en form ?

Jens b
Avatar billede cms Nybegynder
26. september 2001 - 17:32 #23
ABX> Er Cordic-algoritmen 100% præcis?

Jens> Det er ikke nødvendigt at plotte den ud. Jeg spørger mest af nysgerrighed :-)
Avatar billede abx Nybegynder
26. september 2001 - 19:27 #24
Okay , hør nu her CMS :)
Min pointe er, at når det kommer til maskin beregning så findes der ikke nogen algoritme i hele verden der er 100% præcis. Grunden til det er at SINUS ikke kan udtrykkes ved et endeligt antal operationer der kan udtrykkes eksakt på en EDB maskine med fast registerstørrelse.

Cordic algoritemen kan frembringe et tal der så tæt på det eksakte som du ønsker (f.eks. med 30 decimalers nøjagtighed) men den kan aldrig give et eksakt resultat for all værdier af x.

Det samme gælder den tidligere nævnte Taylor polynomium. Ved at medtage tilstækkelig mange led kan du få mange korrekte decimaler som du ønsker.
Husk også at sins er periodisk så du behøver kun at kunne beregne for x liggende mellem 0 og 2*PI.
Så undgår du overflow.
Der er derfor at jeg mener at man ikke kan give et bedre svar. Altå

SIN(X)=x - x^3/(3*2) +x^5/(5*4*3*2) - x^7/(7*6*5*4*3*2)+...
men du kan desværre kun medtage endeligt mange led.






Avatar billede abx Nybegynder
26. september 2001 - 19:34 #25
og det er iøvrigt væsentligt at tilføje

\"men du kan desværre kun medtage endeligt mange led PÅ EN EDB MASKINE\".




Avatar billede cyberlsn Nybegynder
26. september 2001 - 21:54 #26
Meget nemt... Her er lidt begynderprogrammering, så du bedre forstår hvordan man bruger Cosinus og Sinus:

unit Unit1;

interface

uses
    Windows,
    Messages,
    SysUtils,
    Classes,
    Graphics,
    Controls,
    Forms,
    Dialogs,
    ExtCtrls,
    StdCtrls,
    vektorer, Menus;

type
    TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    About1: TMenuItem;
    Exit1: TMenuItem;
    Resize1: TMenuItem;
    N1: TMenuItem;
    N3: TMenuItem;
    Timer1: TTimer;
        procedure FormCreate(Sender: TObject);
    procedure Exit1Click(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure Resize(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);

        private
        public

    end;

var
    Form1: TForm1;

implementation

{$R *.DFM}

type
    coords    = array[0..23] of double;

Const
    lys    : vektor    = (x:0;y:0;z:1);

    per    = 6;
    center  = 180;

        xrot    = 5;
        yrot    = 10;
        zrot    = 4;

    lock    : coords    =
        (-1,-1,-1, -1,-1, 1, -1, 1,-1, -1, 1, 1,
          1,-1,-1,  1,-1, 1,  1, 1,-1,  1, 1, 1);

    index    : array[0..23] of byte =
          (0,1,3,2,
          0,4,5,1,
          0,2,6,4,
          1,5,7,3,
          2,3,7,6,
          5,4,6,7);

var
    buffer    : Tbitmap;
    clean      : Tbitmap;
    v          : double;
    cube      : coords;
        size      : byte;

procedure rotate;

var    x,y,z    : double;
    i    : byte;

begin
    if v>4*pi then v:=0 else v:=v+0.005;

    cube:=lock;

    for i:=0 to 7 do
    begin
        y:=cos(xrot*v)*cube[i*3+1]-sin(xrot*v)*cube[i*3+2];
        z:=sin(xrot*v)*cube[i*3+1]+cos(xrot*v)*cube[i*3+2];
        cube[i*3+1]:=y;
        cube[i*3+2]:=z;

        x:=cos(yrot*v)*cube[i*3]-sin(yrot*v)*cube[i*3+2];
        z:=sin(yrot*v)*cube[i*3]+cos(yrot*v)*cube[i*3+2];
        cube[i*3]:=x;
        cube[i*3+2]:=z;

        x:=cos(zrot*v)*cube[i*3]-sin(zrot*v)*cube[i*3+1];
        y:=sin(zrot*v)*cube[i*3]+cos(zrot*v)*cube[i*3+1];
        cube[i*3]:=x;
        cube[i*3+1]:=y;
    end;
end;

procedure line(x1,y1,x2,y2:word);
begin
    with buffer.canvas do
    begin
        Brush.color:=clBlack;
        MoveTo(x1,y1);
        LineTo(x2,y2);
    end;
end;

procedure pol(x1,y1,x2,y2,x3,y3,x4,y4,color:word);
begin
    buffer.canvas.brush.color:=color;
    buffer.canvas.Polygon([point(x1,y1),point(x2,y2),point(x3,y3),point(x4,y4)]);
end;

procedure draw;

var    i, col            : byte;
    x1,y1,x2,y2,x3,y3,x4,y4    : word;
    v1,v2, n        : vektor;

begin
    buffer.canvas.draw(0,0,clean);

    for i:=0 to 5 do
    begin
        v1.x:=cube[index[i*4+2]*3+0]-cube[index[i*4+0]*3+0];
        v1.y:=cube[index[i*4+2]*3+1]-cube[index[i*4+0]*3+1];
        v1.z:=cube[index[i*4+2]*3+2]-cube[index[i*4+0]*3+2];

        v2.x:=cube[index[i*4+1]*3+0]-cube[index[i*4+0]*3+0];
        v2.y:=cube[index[i*4+1]*3+1]-cube[index[i*4+0]*3+1];
        v2.z:=cube[index[i*4+1]*3+2]-cube[index[i*4+0]*3+2];

        kryds(v1,v2,n);

        if cos_vinkel(n,lys)>0.15 then
        begin
            x1:=round(size*((cube[index[i*4+0]*3+0]*per)/(cube[index[i*4+0]*3+2]+per)))+center;
            y1:=round(size*((cube[index[i*4+0]*3+1]*per)/(cube[index[i*4+0]*3+2]+per)))+center-10;
            x2:=round(size*((cube[index[i*4+1]*3+0]*per)/(cube[index[i*4+1]*3+2]+per)))+center;
            y2:=round(size*((cube[index[i*4+1]*3+1]*per)/(cube[index[i*4+1]*3+2]+per)))+center-10;
            x3:=round(size*((cube[index[i*4+2]*3+0]*per)/(cube[index[i*4+2]*3+2]+per)))+center;
            y3:=round(size*((cube[index[i*4+2]*3+1]*per)/(cube[index[i*4+2]*3+2]+per)))+center-10;
            x4:=round(size*((cube[index[i*4+3]*3+0]*per)/(cube[index[i*4+3]*3+2]+per)))+center;
            y4:=round(size*((cube[index[i*4+3]*3+1]*per)/(cube[index[i*4+3]*3+2]+per)))+center-10;

            col:=round(cos_vinkel(n,lys)*255);

            pol(x1,y1,x2,y2,x3,y3,x4,y4,col);
        end;
    end;

    form1.canvas.draw(0,0,buffer);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    Buffer:=Tbitmap.Create;
    Buffer.width:=380;
    buffer.height:=390;
    clean:=Tbitmap.Create;
    clean.width:=380;
    clean.height:=390;
    form1.width:=380;
    form1.height:=390;

    clean.canvas.Brush.color:=clBlack;
    clean.canvas.polygon([point(0,0),point(0,389),point(379,389),point(379,0)]);

    size:=50;
end;

procedure TForm1.Exit1Click(Sender: TObject);
begin
    Close;
end;

procedure TForm1.About1Click(Sender: TObject);
begin
    ShowMessage(\'af Valdemar Rørbech\'+#13+
            \'valdemar@roerbech.dk\'+#13+
                \'web: http://prog.adr.dk/\');
end;

procedure TForm1.Resize(Sender: TObject);
var      tmp : integer;
begin
    tmp:=strtoint(inputbox(\'3D-terning\',\'Angiv ny størrelse (max. 80)\',inttostr(size)));
    if tmp<81 then
    if tmp>-1 then
    size:=tmp
    else showmessage(\'Ost!\');

end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin
    Rotate;
    Draw;
end;

end.

Programmet laver ikke andet end at rotere et object i 3D, men derfor kan du vel godt bruge til din lommeregner, ik´?

CyberLSN
Avatar billede cms Nybegynder
27. september 2001 - 20:17 #27
CyberLSN: Ser spændende ud, men har du læst spørgsmålet (og kommentarerne)?

ABX: Da du skriver at \'ingen metode er 100% præcis til maskinberegning\' får man lyst til at spørge om der er nogen form for beregning, hvor der findes en 100% præcis metode...

Kan man bestemme, hvor mange led der skal med, før man har en nøjagtighed på x decimaler ?
Avatar billede abx Nybegynder
28. september 2001 - 00:48 #28
Nej det er der vel ikke, tænk blot på
KVADRATROD(2)som ikke kan udtrykkes med et endeligt antal decimaler.
For Taylorudviklingen gælder at hvis du medtager n led så fejlen højst ABS(x)^n / (n!),
hvor n!=1*2*3*..*n og ABS = numerisk værdi.

Altså hvis du f.eks. beregner SIN(x) ved hjælp
af x- x^3/3! + x^5/5! - x^7/7! så er fejlen højst
ABS(x^7)/5040.

Som tidligere nævnt behøver du kun regne i mellem -PI og PI fordi sin er periodisk. Hvis du ønsker at fejlen skal være mindre end , f.eks., 0.00001 for alle x mellem -PI og PI kan du nemt (med lommeregner) finde ud af hvor stor n skal være for PI^n/n! <=0.0001.
(n bliver cirka 15)

For Cordic algoritmen ved jeg ikke hvad der gælder. Nu synes jeg altså at jeg har svaret på dit spørgsmål: \"Nogen der kan give mig en opskrift på hvordan min lommeregner og computer udregner sin(x)\"



Avatar billede abx Nybegynder
28. september 2001 - 01:06 #29
PS : det er langt fra sikkert at fejlen er så stor som skrevet. Det er blot en øvre grænse.
Avatar billede cms Nybegynder
28. september 2001 - 17:53 #30
OKay, takker. Spørgsmålet var blot kort/småt/enkelt formuleret, selvom ønsket måske var stort/komplekst.
Jeg har desuden fordoblet pointene siden jeg stillede spørgsmålet...
Men tusind tak for hjælpen - jeg har afprøvet algoritmen og den virker :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester