Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

cos(x) =?

Status
Not open for further replies.
Radians = degrees * pi/180.
Once x is calculated the relationship with y still holds.
 
Last edited:
For the time being, I've cranked up the micro speed to 32Mhz... It has allowed me to run with two trig functions.... I'll see if I can find an alternate sin ~ cosine routine... Currently 14mS to create an Arc... I need 6 of then so around 84mS is a tad too much, but! Hey ho!
 
I have two functions in a piece of code..

x = cos(a);
y = sin(a);

When using degrees I normally just go.

x = cos(a);
y = 1 - x;

Ian, are you saying that sin(a) = 1 - cos(a) ?
I think that you are a bit off the mark there.

The correct relationship is sin^2 + cos^2 = 1

Which would give y = sqrt(1 - x^2) using your notation.

JimB
 
Ian, are you saying that sin(a) = 1 - cos(a) ?
I think that you are a bit off the mark there.
Yep! Found that out in radians... sin(a) = cos(a + PI/2)... A tad crap for me...

I found a super duper fast routine **broken link removed** But its only a small bit faster than XC8's builtin..

I thought that because cos(30) = 0.86 and sin(60) = 0.86, "Senior moment", it was linear back to front!!

What I do when I use cos for sin is.. cos (30) = sin(90-30) which is correct!! But using radians turned me upside down.
 
I had a quick look through... Its in pascal for the x86 system... A couple of issues.. Namely A) its for 32 bit machine and B) it uses "fmul" and most PC's have a floating point unit... I would like to see how fast it runs turning of the hardware FPU and using the software FPU.

But for my PC ( Lazarus ) projects... Thanks for that!
 
Hi,

Yes i had to look twice when i saw that 1-cos(a) was somehow coming out to sin(a) :)
And yes, rads=degrees*pi/180 so a formula like:
x=cos(a)

in degrees is just:
x=cos(a*pi/180)

The two best forms are probably these two:
x=r*cos(a)
y=r*sin(a)

combined with the circle of radius 'r':
r^2=x^2+y^2

and after substitution of x and y:
r^2=(r*cos(a))^2+(r*sin(a))^2
r^2=r^2*cos(a)^2+r^2*sin(a)^2
r^2=r^2*(cos(a)^2+sin(a)^2)
and using the identity cos(a)^2+sin(a)^2=1 we end up with:
r^2=r^2*1
so:
r^2=r^2

and we've proved the identity.

So we can solve for sin(a)^2 and get:
sin(a)^2=1-cos(a)^2

and taking the square root of both sides we get:
abs(sin(a))=sqrt(1-cos(a)^2)

and so we have to split this into two forms showing principle angles:
sin(a)=sqrt(1-cos(a)^2), for pi<=a<=0 (eg from a=0 to pi)
sin(a)=-sqrt(1-cos(a)^2), for -pi<=a<=0 (eg from a=0 to -pi)

Also note that sin(a) may be more accurate than using the calculation on some angles, especially those close to either 90 degrees or 0 degrees (one of the axes).
 
Last edited:
So MrAl to answer my question

I have a point x,y.. I rotate the point around a central fixed point..
This means I need a vertical component ie... sin(x)
And a horizontal component namely cos(x)

I need to work out cos(x) without trig... Let me explain..

cos(20) = 0.9396... and sin(20) = 0.342... But! sin(90-20) = 0.9396... I "stupidly" assumed that I could use only one trig function.. BUT!! I soon realised that I cannot make the changes after the trig the alterations have to be made before the trig function... I just wondered if it were possible to only use 1 trig function for sin and cos
 
So MrAl to answer my question

I have a point x,y.. I rotate the point around a central fixed point..
This means I need a vertical component ie... sin(x)
And a horizontal component namely cos(x)

I need to work out cos(x) without trig... Let me explain..

cos(20) = 0.9396... and sin(20) = 0.342... But! sin(90-20) = 0.9396... I "stupidly" assumed that I could use only one trig function.. BUT!! I soon realised that I cannot make the changes after the trig the alterations have to be made before the trig function... I just wondered if it were possible to only use 1 trig function for sin and cos

Here you go, Cos{x} without trig once you know the single trig Sin[x]. To find the cosine after the sine is known, subtract from 1, the square of the sine, the extract the square root for the cosine as shown below.

Rogers.JPG
t

Ratch
 

Attachments

  • Rogers.JPG
    Rogers.JPG
    14.5 KB · Views: 285
So MrAl to answer my question

I have a point x,y.. I rotate the point around a central fixed point..
This means I need a vertical component ie... sin(x)
And a horizontal component namely cos(x)

I need to work out cos(x) without trig... Let me explain..

cos(20) = 0.9396... and sin(20) = 0.342... But! sin(90-20) = 0.9396... I "stupidly" assumed that I could use only one trig function.. BUT!! I soon realised that I cannot make the changes after the trig the alterations have to be made before the trig function... I just wondered if it were possible to only use 1 trig function for sin and cos
Hi,

...and so we have to split this into two forms showing principle angles:
sin(a)=sqrt(1-cos(a)^2), for pi<=a<=0 (eg from a=0 to pi)
sin(a)=-sqrt(1-cos(a)^2), for -pi<=a<=0 (eg from a=0 to -pi)

Also note that sin(a) may be more accurate than using the calculation on some angles, especially those close to either 90 degrees or 0 degrees (one of the axes).

Hello again,

As you can see i already answered that last question :)

However, there are also the approxmations as sin(x) can be approximated in many ways.
For example sin(x) can be approximated one way as:
sin(x)=(5880*x-620*x^3)/(11*x^4+360*x^2+5880)

A simple 4 term Taylor series gets you there also:
sin(x)=x-x^3/6+x^5/120-x^7/5040

or:
cos(x)=1-x^2/2+x^4/24-x^6/720+x^8/40320


These are best between 0 and pi/2.
 
I came across this.... As I am working on a small 128x128 screen it will do the job.

It comes from "Ye olde spectrum" but it is very fast...

I post it here for others... it only uses 45 point lookup.
C:
const char sintable[] ={
   0,9,18,27,35,44,53,62,
   70,79,87,96,104,112,120,127,
   135,143,150,157,164,171,177,183,
   190,195,201,206,211,216,221,225,
   229,233,236,240,243,245,247,249,
   251,253,254,254,255,255};

double mycos(double deg)
 {
 return mysin(90-deg);
 }
double mysin(double deg)
 {
 signed int quad;
 int esti, diff;
 while(deg>360)
  deg-=360;
 while(deg<0)
  deg+=360;
 if(deg>180)
  {
  quad= -1;
  deg-=180;
  }
 else
  quad = 1;
 if(deg>90) deg = 180-deg;
 deg/=2;
 diff = (int)deg;
 deg = deg - diff;
 esti = sintable[diff];
 diff = sintable[diff+1] - esti;
 deg *= diff;
 deg += esti;
 return (deg/255)*quad;
 }
Its at least 5 times faster than the math library!!
 
Hi Ian,

Looks very interesting, i'll have to try it out a little later.

Maybe you could help me find an approximation i posted a while back for sin(x)?
I cant seem to find it now.
I posted on this site but not sure if it was in math or not now.
 
Maybe you could help me find an approximation i posted a while back for sin(x)?
XC8 uses approximation, but for what I need its over the top... I am working to int precision so the above is overkill let alone the successive one ..

Here is XC8's sin()..
C:
double sin(double f)
{
 const static double coeff_a[] =
 {
   207823.68416961012,
  -76586.415638846949,
   7064.1360814006881,
  -237.85932457812158,
   2.8078274176220686
 };
 const static double coeff_b[] =
 {
   132304.66650864931,
   5651.6867953169177,
   108.99981103712905,
   1.0
 };
 double x2, y;
 unsigned char sgn;
#ifdef i8086
 if(_use8087)
  return _sin87(f);
#endif
 sgn = 0;
 if(f < 0.0) {
  f = -f;
  sgn = 1;
 }
 f *= 1.0/TWO_PI;
 f -= floor(f);
 f *= 4.0;
 if(f > 2.0) {
  f -= 2.0;
  sgn = !sgn;
 }
 if( f > 1.0)
  f = 2.0 - f;
 x2 = f * f;
 y = eval_poly(x2, coeff_b, 3);
 f *= eval_poly(x2, coeff_a, 4) / y; 
 if(sgn)
  return -f;
 return f;
}

double eval_poly(double x, const double * d, int n)
{
 double res;
 res = d[n];
 while(n)
  res = x * res + d[--n];
 return res;
}

The eval_poly is the successive part..
 
Ian Rogers,
First of all, I would use a look-up table. It can be one degree increments from 0-90. Or, it can be 2 degree increments or more. The same 90° table can be used for the cos because cos(70) is sin(20). The same table can also be used for 0-360 be adjusting the sign of the sines. Once the angle is determined to the nearest degree, the incremental part can be determined. Then use the incremental Taylor series to calculate the sin of the total angle. Suppose we want to calculate the sin of 1.5 degrees. The integer degree part call "a" and the incremental part call "h". The incremental Taylor series is

Rogers.JPG

Applying the above equation and converting a=1 degree and h=0.5 degree to radians, the sin of 1.5 degrees is easily found to be 0.0261769. Notice that successive derivatives of the sin alternate between the sin and cos. Fewer terms or a smaller look-up table can be used if lower precision is acceptable. Observe that the sin changes the fastest at 0 and pi radians, so the precision will be less at that area of the sin.

Ratch
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top