3
\$\begingroup\$

I have one programming question:

The sine and cosine of \$x\$ can be computed as follows:

\$\sin(x) = x - \frac{x^3}{3!} + \frac{x^5}{5!} - \frac{x^7}{7!} + \frac{x^9}{9!} - \dots\$

\$\cos(x) = 1 - \frac{x^2}{2!} + \frac{x^4}{4!} - \frac{x^6}{6!} + \frac{x^8}{8!} - \dots\$

Your task is to compute the sine and cosine for given values of \$x\$ (where \$x\$ is in radians) using the above series up to 5 terms.

Input Format

First line will contain \$N\$, the number of test cases. Next \$N\$ lines will contain the input values of \$x\$:

\$1 \le N \le 50\$

\$0 \lt x \lt 10\$

Each value of \$x\$ can contain up to 2 places of decimal in radians.

Output Format

2 \$N\$ lines, corresponding to the \$N\$ input values of \$x\$. For each input, you will output 2 lines. First line will be the sine and the second line will be the cosine of \$x\$. An error margin of \$\pm\$0.001 will be tolerated while evaluating the answers. Please round off your answer to 3 decimal places.

Sample Input

5
2.83
3.24
0.99
2.74
5.04

Sample Output [sic]

 0.309
-0.943
-0.089
-0.963
 0.836
 0.549
 0.392
-0.914
 0.195
 2.746

and what I have tried:

public class Trigonometric_Ratios
{  
  int factorial(int number)
  {
    int result = 1;
    for (int i = 1; i <= number; i++)
    {
      result = result * i;
    }
    return result;
  }

  void calc(double x)
  {
    double sinx=0,cosx=0;

    int i,j = 0;

    int c;
    for(i=1;i<10;i+=2)
    {
      c=i;
      sinx += Math.pow(-1,j++)*Math.pow(x,i) / factorial(i);
      if(i>0)
      cosx+=Math.pow(-1,j)*Math.pow(x,c-1)/factorial(c-1);
    }
    sinx=Math.round( sinx * 1000.0 ) / 1000.0;

    cosx=-cosx;
    cosx=Math.round( cosx * 1000.0 ) / 1000.0;
    System.out.println(sinx+" \n"+(cosx));
  }

  public static void main(String [] args)
  {
    int n;
    Trigonometric_Ratios tr=new Trigonometric_Ratios();

    Scanner sc=new Scanner(System.in);

    n=sc.nextInt();

    double a[]=new double[n];
    for(int i=0;i<n;i++)
    {
      a[i]=sc.nextDouble();
    }

    for(int i=0;i<n;i++)
    {
      tr.calc(a[i]);
    }
  }
}

Please review my code. In particular, I am concerned about performance, and would appreciate suggestions on reducing the time complexity.

\$\endgroup\$
10
  • 2
    \$\begingroup\$ What a lot of languages, looks a lot like Java to me. Where is the class Trigonometric_Ratios? Does this compile? How do the results look? Homework? I wouldn't worry too much about compile time just yet. \$\endgroup\$
    – JohnMark13
    Sep 20 '13 at 10:00
  • \$\begingroup\$ You can avoid calculating Math.pow(x,i). You need all powers of x 1..9. This can be done simply by multiplying the previous power of x with x. You also need factorial for all values 1..9 so do calculate fractorial(n) by fractorial(n-1)*n. \$\endgroup\$
    – MrSmith42
    Sep 20 '13 at 10:07
  • 2
    \$\begingroup\$ i is always >0 so you can remove the condition if(i>0) from your loop. \$\endgroup\$
    – MrSmith42
    Sep 20 '13 at 10:08
  • \$\begingroup\$ @JohnMark13 yes i correct class name and output is same like question i post here \$\endgroup\$ Sep 20 '13 at 10:23
  • 2
    \$\begingroup\$ The simplest way to reduce time complexity would be to use an array to store the factorial of all values upto 10(which is the max factorial that you are calculating). Doing it once will be much better than calculating the factorial many times which you are currently doing. Also you are calculating power of x 2 times. It would be better to calculate x^(c -1) and then multiply it with x to get x^c. Also the variable c is unneeded. It is i at every iteration of the loop. \$\endgroup\$ Sep 20 '13 at 11:41
2
\$\begingroup\$

Instead of computing Math.pow() from scratch, multiply the previous numerator by x2. (I suspect that Math.pow() uses logarithms so that it can handle the general case.) Also, instead of computing the factorial from scratch, multiply the previous denominator by the next two numbers.

\$\endgroup\$
0
\$\begingroup\$
cos(X) = sum (Cn) where Cn=x^2n/2n!

sin(X) = sum (Sn) where Sn=x^(2+1)n/(2n+1)!

So, Sn=Cn*x/(2n+1)

Cn=S(n-1)*x/2n

Start from C0=1 and compute S0=C0*x, C1=S0*x/2, S1=C1*x/3 etc.

\$\endgroup\$
1
  • \$\begingroup\$ Start … compute … etc saving the space to store not only x*x, but n! or its inverse, too, for 1 < n < 10. How do the accuracies of r / 5040, r / 3 / 8 / 5 / 6 / 7 and r * (1/5040) compare? \$\endgroup\$
    – greybeard
    Oct 8 '17 at 20:52
0
\$\begingroup\$

Since the question calls for a precision of ±0.001, it should be safe to stop iterating as soon as a term has an absolute value of less than 0.0005.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.