You should learn using the debugger, this is typically a problem where running the code under debugger step by step will help a lot, if the loop count is incorrect you will see it immediately.
++ on pwlps' point
Debugger will help you a lot in learning the language. A good practice is right after you write the code, walk through the code pretending you are the computer - do each step yourself and ask yourself is that correct? When you are looping as you did in the code, you should walk the loop more than once:
1, the condition when it doesn't run,
2, the condition when it run the first time,
3, the middle while it is running,
4, the condition when it was about to exit,
5, the condition after it exits (after #4 is satisfied), would it restart? Should it restart?
I mentally walk your code, and when I got to the loop condition, I discern that
the way it works is not the same as you expected. So that may be where the issue is - but then, may be not...
May be your expectation is wrong instead of the code being wrong.You have to walk that and decide for yourself whether it was your expectation is wrong or the code is wrong. Doing so, you will learn and understand it a hack of a lot better.
It is 2:30 in the morning so I'm only going to make a couple of suggestions.
...
...
Concentrate on order of operations or operator precedence. Like I said it is late.
Wizard69's point is important, people get trip up by that all the time. When in doubt, add parenthesis.
That brings us to another important point often missed. The manner you do things affects accuracy. Doing arithmetic operations between
large numbers and small numbers is where you must do considerable thinking about precision. You have in your loop:
small_number * expression_with_very_large_number / even_larger_number;So considerable thought must be done to avoid precision lost.
(a) What variable type you use:You define your sum, t, and x as
float. I don't know what compiler you are using, so I can just apply "standard" or "typical" -- With
float, you would be having 32 bit "single precision" with is 6 to 7 digits only.
double or
long double (if your system supports that) would have a lot more precision.
(b.1) The way you enter it:Be explicit, it will help as you look at the code during development and help in debugging when you look at the code a year later. Being explicit will rely less on defaults which may differ from compiler implementations
x=x*3.14159/180;Your
x is
float as declared.
3.14159 is
double since it is a literal number with a decimal.
180 is a literal without decimal so it is an
int, whereas
180.0 would have been a
double.
So, as entered, you have:
float = float * double / int
I wont go too deep, but you can figure out why I would recommend this:
x = (double) x*3.14159/180.0; // if you have to store x as a float
x = x*3.14159/180.0; // if your x is declared as double
(b.2) Propagation of accuracy errorInside the loop, you have:
t=(t*(-1)*x*x)/(2*i*(2*i+1));So the line expressed in value:
reused_small_value = reused_small_value* very_big_value / even_bigger_value
Not all numbers are divisible within given precision. So when that occurs, you have a lost of precision.
I will start with my recommendation first, the explanation is easier to understand this way.
Store the numerator and the denominator separate:
// don't forget to first initialized Numerator and Denominator
for ( .... ) {
Numerator = (Numerator*(-1)*x*x);
Denominator = (Denominator *(2*i*(2*i+1)));
sum = sum + (Numerator /Denominator);
}
Pretend in one of the loop you have a 20/60, you have 0.33 vs 0.3333 (I am truncating it shorter to illustrate the point), the 0.0033 lost occur only in that loop when you keep the Numerator and Denominator separate. So, once you leave that loop, you have that lost in the division accumulated in the
sum and that is it (until you meet another similar situation).
Verses what you have:
for ( .... ) {
t=(t*(-1)*x*x)/(2*i*(2*i+1));
sum=sum+t;;
....
}
Your 0.0033 lost cause by the division will propagate into the next loop and beyond. Besides the one time in the
sum, the next loop you use the less precise
t to do the multiplication when t=(t*(-1)*x*x)/... is next done, and again, and again in all future loops this point forward.
0.0033 propagate in
sum is unavoidable, the error propagate in
t is avoidable. Each time you do the
t*, you are using a less precise numerator. Worst yet, you multiply that number with a very_large_value, which magnifies that error before you do the next division with an_ever_larger_value.
When you keep Numerator and Denominator separate, each division lost of precision is lost only once in the sum. You don't propagate the prior division precision lost by reusing the
t with inaccuracy from the last precision lost.
EDITed for typo - In an attempt to explain clearly, I was too wordy but that would be too much to change...