ctrigonometrymath.h

Implementing a cosine function in C


I have to implement my own version of the double cos(double x) function present in the <math.h> library of C.

There are some things that I don't understand about the implementation of this function.

Principally, I have to:

receive user input (a double x, for example), implement the Taylor series of a cosine upon that double x then return a double number.

I need to compare my implementation with the built-in double cos(double x), and print it out as well.

My function needs to be precise to the level of 1.0e-6 (which is 1 millionth, 7 decimal points after the number)

It seems that I lack the basic understanding of such implementation, since I stumble upon many problems here.


My user input is incorrect. I applied a double number, and not only it prints out the wrong number, it prints out a random number every time.

The way I have calculated the cosine value, using the Taylor series of a cosine is probably incorrect as well.

The built-in double cos(double x) function is having the same behavior, printing the wrong numbers, and a random number every time.


I have used the GCC complier, and compiled the files with the following line:

gcc -ansi -Wall -pedantic my_cos.c -lm

As you can, every thing about those results is just... wrong: enter image description here


Here is my my_cos.h file:

#define PI 3.1415926535
    
double my_cos(double);

Here is my my_cos.c file:

#include <stdio.h>
#include <math.h>
#include "my_cos.h"

double my_cos(double x) {
  double cos = 1 - ((pow(x, 2)) / (2)) + ((pow(x, 4)) / (24))
      - ((pow(x, 6)) / (1 * 2 * 3 * 4 * 5 * 6))
      + ((pow(x, 8)) / (1 * 2 * 3 * 4 * 5 * 6 * 7 * 8))
      - ((pow(x, 10)) / (1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10));
  return cos * ((PI) / (180));
}

int main() {
  double x;
  printf("Please insert a number:");
  scanf("%f", &x);

  printf("Your number is: %f\n", x);

  printf("using my function:");
  printf("%.7f\n", my_cos(x));

  printf("Using C's function:");
  printf("%f\n", cos(x));

  return 0;
}

This long line double cos = 1 - ((pow(x,2))/(2)) + ((pow(x,4))/(24)) - ((pow(x,6))/(1*2*3*4*5*6)) + ((pow(x,8))/(1*2*3*4*5*6*7*8)) - ((pow(x,10))/(1*2*3*4*5*6*7*8*9*10));

is an implementation of the Taylor series of a cosine:

enter image description here

This line return cos * ((PI)/(180)); is supposed to be a conversion from the degrees form to the radian form, since the built in function also returns the cosine of an argument in radians.

I would more than appreciate to get advice about how to fix those problems and improve my program.


Solution

  • You have to convert the argument of cosine to radians, not the result. Your routine works fine if you just return cos;. Then it matches the cos() function pretty well.

    As noted in the comments, the calculation can be considerably simplified and sped up by factoring:

    
    double my_cos(double x) {
        x *= x;
        return 1 - x/2 * (1 - x/12 * (1 - x/30 * (1 - x/56 * (1 - x/90))));
    }
    

    (That, of course, takes the argument in radians. As any self-respecting cosine implementation should. You should do the conversion before calling the function.)

    Also as noted in the comments, for accuracy this should be used only in the range of 0 to π/2 (or –π/2 to π/2 if that makes the code simpler), with values outside of that converted into that range with the appropriate sign for the result.

    Use M_PI from math.h instead of your own defined (and incorrect) constant.

    Use %lf instead of %f when doing a scanf() into a double.