Thread: Sine (Sin) Algorithm Help

  1. #1
    Registered User
    Join Date
    May 2008
    Posts
    27

    Sine (Sin) Algorithm Help

    So I'm a college student down in Texas and I'm crunching for time atm with finals coming up and programs due in a few days.

    Anyways, my professor gave me this:

    double sin( float value angle){
    Compute the sine of “angle” using as many terms in the series as required till two successive approximations differ by no more than 0.00000001. Hint: see the example for computing square roots. The sine of a number may be found using the following series.
    Sin( x ) = x – x3/3! + x5/5! – x7/7! + ●●●
    }

    To figure out the sin function for my program I need to figure out the algorithm to calc a sin.

    We were also given this snipet of code to help us try to do this, but it is wiht square roots and is very little help to me if I can't figure out how to put the Sin(x)... into algorithm format.
    Here is the code snipet.

    /
    Code:
    / #define EPSILON 0.000001 // Traditional constant definition.
    const double EPSILON = 0.000001;
    
    double sqrt( double n) {
    double guess;
    if (n >= 0.0) {  //verify legal input
    		for (guess = n;
    	    	       !( fabs(guess * guess – n) < EPSILON); 
    	    	      guess = ( ( n + guess * guess) / (2.0 * guess) )
    	          ) /* null body for loop */ ;
    
    		return(guess);
       	}
       	else 
    return (-1.0); //error flag
    }
    Thanks a lot, and if you need anymore details on this, I'd be glad to try to explain better.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Express this in summation notation:
    Sin( x ) = x – x3/3! + x5/5! – x7/7! + ...

    This will give you the formula for one term. With that formula, you can easily write a for loop. Instead of looping to infinity, loop to some arbitrary maximum. Test that your implementation works. Only when you have checked that your implementation at this point is correct then begin to think about how to implement the requirement to terminate when "two successive approximations differ by no more than 0.00000001".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    May 2008
    Posts
    27
    Oops! Looks like it didn't format it correctly.

    Sin( x ) = x – x^3/3! + x^5/5! – x^7/7! + ●●●

    So instead of it being x times 3, it is x up to the third power. Sorry about that. But what do you mean summation notation?

    I'm guessing it is something like this, except this is for the square root function.
    R(n+1) = (X + R(n)**2) / (2 * R(n))

    Thanks for the quick reply

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    But what do you mean summation notation?
    You should have learnt this in elementary mathematics, but perhaps you are not familiar with the term: Summation Notation

    I'm guessing it is something like this, except this is for the square root function.
    R(n+1) = (X + R(n)**2) / (2 * R(n))
    That is a recurrence relation, not a sum expressed in summation notation.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    May 2008
    Posts
    27
    Would it be something like this (Sorry, I remember what it is, but I have never been good at creating them.. Never actually been taught on how to even try to do it, so here goes.)

    Summation of ((x^n)/n!) - ((x^n+2)/(n+2)!) ? Or something close to it?

    Thanks again.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Summation of ((x^n)/n!) - ((x^n+2)/(n+2)!) ? Or something close to it?
    You're close, but the problem is that that is two terms. You can still write a for loop with 2 terms, but it will affect the "two successive approximations differ by no more than 0.00000001" requirement since you would only be able to terminate when two successive pairs of approximations differ by no more than some value.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    May 2008
    Posts
    27
    So maybe this... (x^n/n!) * -1?

    I'm really trying to understand this.. I just can't seem to understand how to get it going from x^3 to x^5 ... in increments of two, and also the whole adding and subtracting thing.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    So maybe this... (x^n/n!) * -1?
    Ah, you have the right idea. It would be more like:
    n = 0 to infinity
    sine(x) = (-1)^n * (x^(2n+1) / (2n+1)!)

    Now, note that you do not actually need to compute (-1)^n. Rather, note that when n is even you add to the sum, and when it is odd, you subtract from the sum.

    You also do not need to compute x^(2n+1) in full on each iteration of the loop. Rather, note that on the previous iteration you already calculated x^(2n-1), so now you just need to multiply that with x^2. Likewise, you do not need to compute (2n+1)! in full on each iteration of the loop.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    May 2008
    Posts
    27
    Awesome! Now lets see if I can actually write out the loop and then figure out the other part.
    Code:
    for (i = 1; i < 10; i++)
    {
        if (i % 2 == 0)
        {
             x = x + (x^(2i+1)/(2n+1)!);
         }
        else
        {
            x = x - (x^(2i+1)/(2n+1)!);
         }
    }
    I think this will work, it just wont be as effective as your suggestion, but again, it is like 6 am and I had troubles understanding how to get it to the initial value to be able to just do x^2.

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Obviously, you don't want to update x (as that is your input of the angle in radians), but I take that's a typo.

    You can do the if(i % 2 == 0) "automatically" by just having a variable sign that you set to 1 to begin with, then alternate the sign as you loop through (sign = -sign), and multiply into the calculation. That is highly likely to be faster than the %2 check (even if the compiler optimizes it to better than "divide by two").

    You can also calculate the (2n+1)! as part of your loop, rather than doing a factorial each iteration. d = d * i * (i +1) or something like that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    May 2008
    Posts
    27
    Yeah, that was a typo, so here is maybe a better one.
    Code:
    int d = 1;
    double y = x;
    double m = -1;
    for (i = 1; i < 10; i++)
    {
        k = 2*i+1;
        d = d * k * (k-1);
         y = y + m*(y^k/d);
    }
    return y;
    How is this? I'm still trying to get it to the beginning part. but I think this is a better start.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You still accumulate in the same variable that you have as input to the calculation.

    Code:
    y = y + m*(x^k/d);
    Edit: And ^ is not "raised to the power of". Again, you can achieve this by having a "x2p1" variable that is intialized with x, and then multiplied by -1*x*x.

    --
    Mats
    Last edited by matsp; 05-09-2008 at 06:35 AM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    May 2008
    Posts
    27
    I'm sorry if this is frustrating, but I really don't know what a x2p1 variable is. But yeah, I'm sorry about the ^ thing, meant to put **, but oh well. Bleh, I actually feel more confused now.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well ** doesn't work in C either - but if you are just writing it symbolically, then that's fine.

    The x2p1 is "x to the power of 2n+1" - perhaps there is a better name for that, but my point is that you don't need to calculate x**(2n+1) each time you do the loop, but instead, you can calculate x**(2n+1) iteratively by just multiplying the current value by x *x - and to fix up the sign, multiply by -1 as well.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    May 2008
    Posts
    27
    The ** doesn't work in C? Lol.. I've been programming in Ada for too long then.

    So, instead of the x**(2n+1) I just use x*x *-1, or would it be y = y *x*x*-1? (Again, sorry if it is annoying, I'm just trying to learn C, and to pass my class with an understanding of the language. But C is very new to me)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Implement of a Fast Time Series Evaluation Algorithm
    By BiGreat in forum C Programming
    Replies: 7
    Last Post: 12-04-2007, 02:30 AM
  2. Replies: 4
    Last Post: 12-10-2006, 07:08 PM
  3. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM