Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Mugambo

macrumors 6502
Original poster
Jul 4, 2009
286
0
I have compiled the program and it executes.
But soon after I give a value say 30 (i.e. to find sin 30) cursor keeps blinking with no response.
Along with C, I'm learning C++ from books.

Code:
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

class value {
    float n, x, fct, count;
    public:
    void getx() {
        cout<<"Enter a number"<<endl; cin>>x; fflush(stdin);
    }
    float fact(float j) {
        fct=1;
        while(1) {
            fct=fct*j; j++;
        }
        return fct;
    }
    void sinx(){
        float sinxx;
        count=-1;
        float i;
        i=1;
        sinxx=0;
        while(i<=10){
        count*=count;
        sinxx=sinxx+count*((pow(x,i))/fact(i));
        i+=2;
        }
        printf("sin of %d is %f", x, sinxx);
    }
};

int main()
{
    value sed;
    sed.getx();
    sed.sinx();
    return 0;
}
 
This:

Code:
 float fact(float j) {
        fct=1;
        while(1) {
            fct=fct*j; j++;
        }
        return fct;
    }

looks very wrong to me. I'm not C++ expert but how does the while loop ever terminate?
 
Code:
    float fact(float j) {
        fct=1;
        while(j>=1) {
            fct=fct*j; j--;
        }
        return fct;
    }

Thank you for the help.
Not able to get accurate results yet.
Help please.
 
Code:
    float fact(float j) {
        fct=1;
        while(j>=1) {
            fct=fct*j; j--;
        }
        return fct;
    }

Thank you for the help.
Not able to get accurate results yet.
Help please.

Then work through the code on paper and work out why. Debugging is a core part of programming. Simply saying "it's not working" and getting someone else to study, analyse and fix is not.
 
Thank you for the help.
Not able to get accurate results yet.
Help please.

For small x, let's say less than 1, sin (x) is close to x. Do you get that? If yes, that's a start.

The sine function has arguments in radians, not in degrees. What is sin (0), sin (pi/2), sin (pi), sin (3pi/2), sin (2 pi) and how does it go on after that? You know what the sine curve looks like, don't you?

For large x, like the 30 which you mention, which is close to 9.5 pi, the Taylor formula isn't very accurate. What about printing out the values that you are adding up?

And then of course you should check the value of "count". Which is badly named, because it doesn't count anything. Probably meant to be called "sign".
 
Robbieduncan, that's a piece of advice which I'm sure no book can offer. I truly thank you for that. Debugging on paper got me there!

Got it finally!
I'm getting accurate results for values entered between sin(-11) and sin(11). Beyond that results are inaccurate. This is due to reduced iterations.
Simply increasing iterations/(no. Of passes) seems to have a limit after which junk values are displayed.
In my case anything over 250 iterations is causing junk values.

Any best practices to follow in order to avoid above scenario will be helpful.
 
Gnasher, great heads up on the sine wave! Now I got a clear picture. Very helpful, thanks. This answers my above post. Please ignore above post btw.
 
Any best practices to follow in order to avoid above scenario will be helpful.

The best practice is to learn how to use the debugger. Then use it.

With a debugger, you can set breakpoints on functions and lines in functions, then step through a line at a time. You can also examine variables while stopped at a breakpoint, or stepping through.

If your book doesn't teach you how to use the debugger, find one that does.
 
Last edited:
Robbieduncan, that's a piece of advice which I'm sure no book can offer. I truly thank you for that. Debugging on paper got me there!

Got it finally!
I'm getting accurate results for values entered between sin(-11) and sin(11). Beyond that results are inaccurate. This is due to reduced iterations.
Simply increasing iterations/(no. Of passes) seems to have a limit after which junk values are displayed.
In my case anything over 250 iterations is causing junk values.

Any best practices to follow in order to avoid above scenario will be helpful.

Again, print out the values that are added up. If x >= 3, then these values will first grow and then become smaller. Your initial code failed because the number of iterations was too low, and you dropped values that were still quite large. But if x > 20, you will see that these values can become _very_ large, and adding them will just produce huge rounding errors. Since -1 <= sin x <= 1, as soon as the rounding error is > 1, your results will be nonsense.

Try first what happens if you replace "float" with "double" and "long double". It will improve things, but not solve the problem. However, in many cases just using "double" will make a solution good enough, so you should _never_ use float (until you reached the point where you don't need to follow anyone's advice).

The second thing which solves this particular problem: There is a formula for the sine function

sin (x + 2pi) = sin (x).

Obviously sin (x + k * 2pi) = sin (x) for every integer k.

So you take x / (2pi), rounded to the nearest integer, call the result k, and subtract k * 2pi from x before you start calculating.
 
Simply increasing iterations/(no. Of passes) seems to have a limit after which junk values are displayed.
It is a rather typical result in evaluating mathematical functions on a computer. Too many iterations often leads to wrong results as errors accumulate. The main reason for this is that calculations are done with a finite precision, ie a maximum number of decimals in the number. A series that in "pure" mathematics converges on a value might very well start swinging between very different values or slowly move away from the correct value.

There is a whole branch of science known as numerical methods that deals with this kind of techniques. It is taken as courses on advanced level in universities, but if you are interested there is a lot of interesting material freely available on the net. Using methods in that area allows you to calculate the optimum number of iterations for this kind of algorithms, depending on what precision the numbers use (float, double float or even longer floats).

A quick fix for your algorithm would be to scale the input before running the algorithm. This works as the sin function is periodic and the input can be scaled to between 0 and 2*pi. You could actually scale to between 0 and 1/2*pi and do some mirroring as a last step.

Have fun // Gunnar
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.