Need some help with a task from my homework.
They gave us a series to calculate cosine, which is:
Σ(-1)^ix^2i/(2i)!
And the task is to implement this in C program by writing a function that takes angle x, and calculate it's cosine. The series should continue summing until the next addend in the series is less then 1.0e-6 (0.000001). I did this and it works good only for small numbers, if I put big numbers as angle, the program get stuck.
#include <stdio.h>
#include <math.h>
#define PI 3.141592
double my_cos(double angle);
int main() {
double angle, radian, my_res, their_res;
printf("Please type a number... \n");
scanf("%lf", &angle);
radian = angle * (PI/180);
my_res = my_cos(radian); /* result from my custom cosine function */
their_res = cos(radian); /* result from the cos function located in the library math.h */
printf("My result is: %f \nMath.h library result is: %f \n", my_res, their_res);
return 0;
}
.
#include <math.h>
#define ACCURACY 1.0e-6
long factorial(int x);
double my_cos(double angle){
int i = 0;
double sum = 0, next_addend;
do {
next_addend = pow(-1, (i+1)) * pow(angle, 2*(i+1)) / factorial(2*(i+1));
sum += pow(-1, i) * pow(angle, 2*i) / factorial(2*i);
i++;
} while ( ACCURACY < fabs(next_addend) );
return sum;
}
/* return the factorial of a given value */
long factorial(int x){
if ( x == 0 ) {
return 1;
}
return(x * factorial(x - 1));
}
If I run the program and insert 45:
But if I insert 300, the program is just "waiting":
I guess it related somehow to the factorial function?
I will really appreciate your help..
Depending on whether sizeof(long) is 4 or 8 on your system you can only calculate 12! or 20! inside a long. Also, calculating multiple pow at every iteration is very inefficient.
For a better solution, try to find out how to calculate the next_addend if you know the previous addend (hint: calculate their ratio on a piece of paper).
Related
i'm just starting with getting to know C, and i'm now following the cs50 course. i have a question on the following code.
I want to calculate the avarage score of the user input.
#include <cs50.h>
#include <stdio.h>
int main(void)
{
int s = get_int("how many scores? ");
int sum = 0;
int score[s];
for(int i = 0; i < s; i++)
{
score[i] = get_int("score: ");
sum = sum + score[i];
}
float avg = sum / s;
printf("avarage: %f\n", avg);
}
So, it prints the avarage, but gets round down to .0000.
Is it because i am using a int to divide by? i have tried several things, like changing int to float, but without result.
How do I solve this?
This is an integer division:
float avg = sum / s;
Which means that 3 / 2 will be 1 (the decimal part is discarded). This will then be stored in avg as 1.f.
You need to make it into a floating point division. You can cast one of the operands to the desired type:
float avg = (float)sum / s;
Now both operands (sum and s) will be converted to float before the actual division takes place and the correct result will be shown, which is 1.5 + some zeroes in the example above.
#Ted's answer (integer division) is the reason your results were not as expected.
For your consideration, I've rewritten your code to be more concise. (The less code there is, the easier it can be to read and understand (as you learn more about C.))
#include <cs50.h>
#include <stdio.h>
int main() // 'void' is unnecessary
{
double sum = 0.0; // make the accumulator floating point
int s = get_int( "how many scores? " );
for(int i = 0; i < s; i++) // no need for braces when...
sum += get_int( "score: " ); // everything happens on one line
/* Above: you may not have seen "+=" before. Find out. Aids clarity */
printf("avarage: %lf\n", sum / s ); // float division result is printed.
}
And, the same thing again to compare without comments
#include <cs50.h>
#include <stdio.h>
int main()
{
double sum = 0.0;
int s = get_int( "how many scores? " );
for(int i = 0; i < s; i++)
sum += get_int( "score: " );
printf("avarage: %lf\n", sum / s );
}
I am new to C and stack overflow so i'm not really sure where to ask the question. I have to make code for population growth. X is the starting population and Y is the end population. I have to calculate time (T). Every year there are X/3 newborns and X/4 deaths. The formula I am using is log(base: 1+(X/12)/100)(Y/X). To test I use 100 as starting population and 200 as the end population. The years are 8.66 which is rounded up to 9 years. I tried changing the variable type but i'm not sure which type I should use. The code is below. Thanks in advance.<
#include <cs50.h>
#include <stdio.h>
#include <math.h>
double log_a_to_base_b( double a, double b)
{
return log(a) / log(b);
}
int main(void)
{
// Prompt for start size
int X;
do
{
X = get_int ("How many llamas do you start with? \n" );
}
while (X < 1);
// Prompt for end size
int Y;
do
{
Y = get_int ("How many llamas do you have after a certain period of time? \n" );
}
while (Y < 1 || Y < X);
// Calculate number of years until we reach threshold
double a = Y/X;
double b = 1+(X/1200);
{
printf("Start size : %i \n", X );
printf("End size : %i \n", Y);
printf("Years:%f \n", log_a_to_base_b(a, b));
}
return 0;
}
I tried the following,
unsigned int log_a_to_base_b( unsigned int a,unsigned int b)
{
return log(a) / log(b);
}
int main(void)
{
printf("%u\n", log_a_to_base_b(10,2)); // Yields 3
return 0;
}
It always returns the correct answer in integer. You will have to change the %f in your printf. I think that rest of the program runs fine. But you still need to understand that all of the divisions in main are being done on integers. So they will not get you precise results (e.g 3/2=1.000). And you are also returning unsigned int, so that will always give highest integer smaller than the log.
I have an assignment where my professor wants us to calculate sin(x) using a taylor series. He wants us to stop the iterations when the difference between two consecutive fractions is less than 10^-6.
I ended up approaching the problem by saying that for example x^5/5! is the same as (x^3/3!) * (x^2/4*5) and that this is true for all the fractions. So I can just keep the previous fraction I calculated and use it on the next iteration. Problem is the number I end up with is a bit off from its actual sin and I can't figure out why.Thanks in advance. Here is my code:
#include <stdio.h>
#include <Math.h>
#define pi 3.14159265358979323846
int main(int argc, int **argv){
int sign = -1, pwr = 3;
double previous, current, rad,sum, degr;
printf("Calculating sin using Taylor Series\n\n");
printf("Give degrees: ");
scanf("%lf", °r);
// translate to rads
rad = degr*(pi/180);
sum = rad;
previous = rad;
do{
current = (previous * pow(rad, 2))/(pwr* pwr-1);
sum += sign*current;
pwr += 2;
sign *= -1;
}
while(abs(current - previous) > pow(10, -6));
printf("The sin of %lf degrees is ", degr);
printf("%.6f\n", sum);
printf("%.6f", sin(rad));
return 0;
}
You're using the abs function, which expects an int and returns an int. This results in the loop existing if the difference between the current and prior term is less than 1 as it will set diff to 0.
Instead, you want fabs which expects and returns a double.
I'm trying to use cosine and sine, however they do not return the value I'm expecting.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main() {
float magnitudeForce;
int force;
float theta;
float angle;
double x;
double y;
int i = 0;
while(i < 3){
printf("Please enter the value of the force"
" and the angle from the x-axis of the force:\n");
scanf("%d %f", &force, &angle);
printf("The force and the angle are: %d %.2lf.\n", force, angle);
x = force * cos(angle);
printf("%lf\n", x);
++i;
}
return 0;
}
So if the force is 8 and the angle 60 then the return should be 4, but it is returning -7.62.
The C cos function requires its argument to be in radians rather than degrees.
While the cosine of sixty degrees is 0.5, the cosine of 60 radians is about -0.95, which is why you're seeing -7.62 when you multiply it by eight.
You can fix this by doing something like:
x = force * cos(angle * M_PI / 180.0);
Keep in mind that M_PI is a POSIX thing rather than an ISO thing so it may not necessarily be in your C implementation. If it's not, you can just define it yourself with something like:
const double M_PI = 3.14159265358979323846264338327950288;
I have been struggling with this code and just do not seem to grasp what I am doing wrong.
The code is suppose to calculate : Sum of a series of "Cosine" with pattern [(-1)^i(x)^2i]/(2i)!
Here is my code thus far:
#include <stdio.h>
#include <math.h>
float factorial(int n){
if (n==0)
return 1;
else
return 2*n*factorial(n-1);
}
int main (){
float i, n;
float sum=0;
printf("Enter desired interger: ");
scanf("%f", &n);
for (i=0; i<=1; i++)
sum = sum + (pow(-1,i)*pow(n,2*i))/(factorial(n));
printf("The value is %f\n", sum);
return 0;
}
I still working on it, any info or help will be much appreciated!
edit:
Just fixed it guys, this is new format I had to use for my professor:
#include <stdio.h>
#include <math.h>
int factorial(int n)
{
if (n==0) return 1;
else
return n*factorial(n-1);
}
float mycos(float x)
{
float sum=0;
int i;
for (i=0;i<=10;i++) sum = sum + (pow(-1,i)*pow(x,2*i))/factorial(2*i);
return sum;
}
int main()
{
int i=1;
printf(" x mycos(x) cos(x)\n");
for (i=1;i<=10;i++)
printf(" %f %f %f\n", i*.1, mycos(i*.1), cos(i*.1));
return 0;
}
Thank you all for your explanations, they helped out Immensely!
One thing I see, is that your for loop within main only runs through 2 real iterations, once for i == 0, and again for i == 1.
For the taylor expansion to work fairly effectively, it needs to be run through more sequence terms (more loop iterations).
another thing I see, is that your denominator is the n! rather than (2 * n)!
For efficiency, I might also implement the factorial routine as follows:
unsigned int factorial(int n){
unsigned int product = 1;
for(int I = 1; I <= n; I++) product *= I;
return product;
}
The above factorial routine is for a more EXACT factorial calculation, which perhaps you don't need for this purpose. For your purposes, perhaps the floating point variant might be good enough.
float factorial(int n){
float product = 1;
for(int I = 1; I <= n; I++) product *= (float)I;
return product;
}
I should also note why I am stating to perform factorial in this manner. In general a loop construct will be more efficient than its recursive counterpart. Your current implementation is recursive, and thus the implementation I provide SHOULD be quite a bit more efficient from both performance, and memory utilization.
Considering computation expense, you need to stop calculating the series at a point. The more you go, the more precise the result will be, but the more your program spends time. How about this simple program:
#include <stdio.h>
#include <math.h>
#define ITERATIONS 10 //control how far you go
float factorial(int n){
if (n==0)
return 1;
else
return n*factorial(n-1);
}
int main (){
float n;
float sum=0;
printf("Enter desired float: ");
scanf("%f", &n);
int c, i;
for (i=0; i<=ITERATIONS; i++) {
c = (i%2)==0? 1 : -1;
sum = sum + (c*pow(n,2*i+1))/(factorial(2*i+1));
}
printf("The value is %f\n", sum);
return 0;
}
1.) You are only multiplying even no.s in factorial function return 2*n*factorial(n-1); will give only even no.s. Instead you can replace n with 2n here- sum = sum + (pow(-1,i)*pow(n,2*i))/(factorial(2n)); This will give the correct (2n!).
2.) Check for the no, of iterations for (i=0; i<=1; i++) this will only run your loop twice. Try more no. of iterations for more accurate anwer.
Why are you calculating power etc for each item in the series? Also need to keep numbers in a suitable range for the data types
i.e. for cos
bool neg_sign = false;
float total = 1.0f;
float current = 1.0f;
for (int i = 0; i < length_of_series; ++i) {
neg_sign = !neg_sign;
current = current * (x / ((2 * i) + 1)) * (x / (( 2 * i) + 2));
total += neg_sign ? -current : current;
}
EDIT
Please see http://codepad.org/swDIh8P5
#include<stdio.h>
# define PRECISION 10 /*the number of terms to be processed*/
main()
{
float x,term=1,s=1.0;
int i,a=2;
scanf("%f",&x);
x=x*x;
for(i=1;i<PRECISION;i++)
{
term=-term*x/(a*(a-1));
s+=term;
a+=2;
}
printf("result=%f",s);
}
Your factorial() function actually calculates 2n.n!, which probably isn't what you had in mind. To calculate (2n)!, you need to remove the 2* from the function body and invoke factorial(2*n).