-1.#IND00 output for certain input values - c

I'm trying to write a code that will take x as input and give cos(x) as output, using maclaurin's series.I'm using a while loop until the difference of two consecutive results is less then 0.001. I'm using double type to accomodate larger values.
the code works when x is in range [-2,2], but if x is greater or less than this range the ouput is -1.#IND00. Why is it happening? is the output value out of range ? how can i fix this ??
my code is :
#include <stdio.h>
double abs(double a);
double power(double p, int q);
int fact(int a);
int main()
{
int i=1,j=2*i;
double x,s=1.0,p,l=0.001;
printf("Enter x: ");
scanf("%lf", &x);
p = s+ power(-1,i) * power(x,j) / fact(j);
while (abs(p-s)>l){
i++; j=2*i;
s=p;
p = s+ power(-1,i) * power(x,j) / fact(j);
}
printf("cos(%f) = %f", x,p);
return 0;
}
double abs(double a)
{
if (a>=0) return a;
else return (-a);
}
double power(double p, int q)
{
int i;
double a=1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
int fact(int a)
{
int i,p=1;
if (a==0 || a==1) return 1;
else
while (a!=1){
p=p*a;
a--;
}
return p;
}

update your scanf function to
scanf("%lf", &x);
Also you need to check pow and fact, these functions could overflow. Especially, fact which only use int.

As a larger |x| is use, more terms are needed and fact() overflows and strange results follow. Use double.
// int fact(int a)
double myfact(double p, int q) {
int i;
double a = 1.0;
for (i=0; i<q; i++){
a=a*p;
}
return a;
}
Eventually with values somewhere larger |x| > 30, other limitations kick in using this method. The limitation is due to precision and not range. For large values a significantly different algorithm should be used.
Potential conflict between int abs(int j) in <stdlib.h>. The prototyped may be found via stdio.h and conflicts with OP double abs(double a). In any case, abs() is a standard library function and OP should avoid that function name. Also recommend renaming power().
// double abs(double a)
double myabs(double a)

Related

Solution to heat equation

When trying to plot the solution of the heat PDE I've found some troubles. The solution that I've found is:
Here is the code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#define N 10000
double f(double x);
double X[N];
double Y[N];
int main(){
int i;
double b=43351/94400;
double dx=0.0001;
X[0]=0;
Y[0]=b;
for (i=1; i<N; i++){
X[i]=X[i-1]+dx;
Y[i]=f(X[i]);
}
FILE* output;
output = fopen("dades.txt", "w");
fprintf(output, "x Posició Temperatura\n");
for (i = 0; i < N; i++){
fprintf(output, "%lf %lf %lf\n", i*dx, X[i], Y[i]);
}
fclose(output);
return 0;
}
double f(double x){
int n;
double b=43351/94400;
for (n=1; n<N; n+=2){
double pi=3.14159265358979323846;
double t0=0.025;
double result=b;
result+=2*(1-pow((-1),n))/(pi*n)*(1-exp(-pow(n,2)*pow(pi,2)*pow(t0,2)))/(pow(n,2)*pow(pi,2))*sin(n*pi*x);
}
return result;
}
What I'm trying to do is to declare a function that calculates the infinite sum for n odd, and then looping it for every x between 0 and 1. The problem is that I don't know how to declare "result" in order to be the sum of all the terms, because if I declare it outside the for loop it doesn't satisfy the boundary conditions.
(Note that I fixed t=0.025).
According to the equation, you can implement f as:
#define M_PI 3.14159265358979323846;
double f(double x)
{
int n;
double result=43351.0/94400.0;
double t0=0.025;
for (n=1; n<N; n+=2){
result+=2*(1-pow((-1),n))/(M_PI*n)*(1-exp(-pow(n,2)*pow(M_PI,2)*pow(t0,2)))/(pow(n,2)*pow(M_PI,2))*sin(n*M_PI*x);
}
return result;
}
Since you are using double, so you have to explicitly add a .0 otherwise it may be considered as integer.
The declarations of variable are moved outside the loop in order both to clarify the code and ensure the variable result gets update instead of being overwritten.
EDIT:
You could improve the function f to take the value of t as an input. This also aligns with the equation provided. It would then implements this way:
double f(double x, double t)
{
int n;
double result=43351.0/94400.0;
for (n=1; n<N; n+=2){
result+=2*(1-pow((-1),n))/(M_PI*n)*(1-exp(-pow(n,2)*pow(M_PI,2)*pow(t,2)))/(pow(n,2)*pow(M_PI,2))*sin(n*M_PI*x);
}
return result;
}
EDIT:
The implementation of the math of the equation could be further simplified:
a^2 b^2 is same as (ab)^2.
(-1)^n with n odd is always -1.
2*(1-pow((-1),n)) is a replacement for 4.
Plus, from a performance perspective you can avoid recalculation of repeated terms by putting them in a variable and the use it as you need (for instance the n^2 pi^2).

Write a C function to evaluate the series // sin(x) = x-(x3 /3!)+(x5 /5!)-(x7 /7!)+... // up to 10 terms

#include <stdio.h>
#include<math.h>
int series(float,float);
int main()
{
float x,n,series_value;
printf("Enter the value of x: ");
scanf("%f",&x);
printf("\nEnter the value of n: ");
scanf("%f",&n);
series_value=series(x,n);
printf("\nValue of series sin (%.2f) is: %f\n",x,series_value);
return 0;
}
int series(float x,float n)
{
int i,sum=0,sign=-1;
int j,fact=1,p=1;
for (i=1; i<=(2*n)-1; i+=2)
{
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
sign=-1*sign;
sum=sum + sign*p/fact;
}
return (sum);
}
Output:
Enter the value of x: 5
Enter the value of n: 10
(lldb)
and this message
Thread 1: EXC_ARITHMETIC (code=EXC_I386_DIV, subcode=0x0)
![Thread 1 Queue : com.apple.main-thread (serial)
]1
Why is this message coming? and what is wrong in the program as answer is not coming right
There is a few problems with your code. As #PaulHankin said, when fact overflows and becoms zero, you will have a division by zero, and "weird things" happen.
Your factorial and power calculation is also wrong. You are recalculating it in each iteration of the outer loop without reseting fact and p first:
fact = 1; // You need to reset fact and p to its start value here
p = 1;
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
Your third problem is that for your function calculate the correct value for sin, which is not an integer value, you need to use float, or even better double, when calculating sum. So sum must be declared float, and the division p/fact must use float division. By also declaring p and fact as float, you will solve both the overflow issue, and use the correct division. Naturally your function must also return a float
float series(float x,float n)
{
int i,sign=-1;
int j,
float sum = 0;
float fact = 1;
float p = 1;
for (i=1; i<=(2*n)-1; i+=2)
{
fact = 1;
p = 1;
for (j=1; j<=i; j++)
{
p=p*x;
fact=fact*j;
}
sign=-1*sign;
sum=sum + sign*p/fact;
}
return (sum);
}
This code still has a minor problem. By having an inner loop, it is slower than necessary. Since this probably is homework, I am not getting rid of that loop for you, just giving you a hint: You don't have to recalculate fact from scratch on each iteration of the outer loop, just try to find out how fact changes from one iteration to the next. The same goes for p.
//Series of Sinx
#include<stdio.h>
#include<math.h>
#define ACCURACY 0.0001
int factorial(int n);
int main()
{
float x,sum,term;
int i,power;
printf("Enter value of X: ");
scanf("%f",&x);
i=1;
power=3;
sum=x;
term=x;
while(term>=ACCURACY)
{
term = pow(x,power) / factorial(power);
if(i%2==1)
{
sum -= term;
}
else
{
sum += term;
}
power+=2;
i++;
}
printf("sin(%f) = %.6f\n",x,sum);
return 0;
}
int factorial(int n){
int i=n,fact=1;
for(i=1;i<=n;i++)
{
fact=fact*i;
}
return fact;
}
plenty bugs. To do not caclulate the fact values all the time they are in the lookup table
#include <stdio.h>
#include <math.h>
double series(double,int);
long long fact[] = { 1, 2, 6, 24,
120, 720, 5040, 40320,
362880, 3628800, 39916800, 479001600,
6227020800, 87178291200, };
double mypow(double x, unsigned p)
{
double result = x;
while(p && --p)
result *= x;
return result;
}
int main()
{
for(double x = 0; x <= M_PI + M_PI / 60; x += M_PI / 30)
printf("Value of series sin (%.2f) is: %f\n",x,series(x, 5));
fflush(stdout);
}
double series(double x,int n)
{
double sum = x;
int i,sign=1;
for (i=3; i<=(2*n)-1; i+=2)
{
sign=-1*sign;
sum += sign*(mypow(x, i)/fact[i -1]);
}
return (sum);
}
https://godbolt.org/z/U6dULN
maybe its due to floating-point exception as u have declared that the function should return int type value
int series(float,float);//hear
so u can try editing the return type of this function as float
Note:-also u need to change at function definition and the datatype of
int i,sum=0,sign=-1;
int j,fact=1,p=1;
to float as it is returning the value (sum) which should also be float

Recursion function; "...has stopped working"

I am trying to make a program that gives a specific sum until some point that I define, here it is:
float sum(int n,float m);
main(void) {
float a,m=1.0;
int n;
scanf_s("%ld", &n);
a = sum(n, m);
printf("%f", a);
}
float sum(int n, float m) {
if ((n/m) < 0.0005) {
return 0;
}
else {
return n/m + sum(n, m + 2);
}
}
(Notice that the point I defined is 0.0005) When I give a value bigger or equal to 5, program gives me this error:
...has stopped working
Also, when I increase the defined point to like 0.5, the number of values I can give increases too. Why do you think is this happening and how can I fix it?
The %ld format specifier to scanf_s expects a long int * argument. What you're passing in is a int *. These types are incompatible. Using the wrong format specifier invokes undefined behavior, which in this case manifests as a crash.
The proper format specifier for an int * is %d:
scanf_s("%d", &n);
EDIT:
The crash you're seeing is probably a stack overflow. The sum function will recursively call itself 1000 * n times. I see a similar error under MSVC but at a different limit. You can get around this by going with an iterative solution:
float sum(int n, float m){
float result = 0;
while ((n/m) >= 0.0005){
result += n/m;
m+=2;
}
return result;
}

C Program to Calculate Hypotenuse

I'm fairly new to coding and am currently learning C. In class I was given an assignment to write a program that calculates the hypotenuse of the triangle by using our own functions. However, there seems to be something wrong with the code that I have written.
#include <stdio.h>
#include <math.h>
double hypotenuse(double x, double y, double z);
int main(void) {
double side1, side2, side3, counter;
side3 = 1;
for (counter = 0; counter <= 2; counter++) {
printf("Enter values for two sides: ");
scanf_s("%d %d", &side1, &side2);
printf("%.2f\n", hypotenuse(side1, side2, side3));
}
return 0;
}
double hypotenuse(double x, double y, double z) {
x *= x;
y *= y;
z = sqrt(x + y);
return z;
}
My instructor said that we're allowed to use the square root function sqrt of the math library. The main errors that I'm facing are:
1) side3 is not defined (This is why I just arbitrarily set it to 1, but is there some other way to prevent this error from happening?)
2) If I, for example, inputted 3 and 4 as side1 and side2, then side3 should be 5. However, the printed result is an absurdly long number.
Thank you for the help! Any words of advice are appreciated.
You don't need side3 variable - it is not used in calculation. And you function hypotenuse returns the result, so you can directly output the result of sqrt.
I use Ubuntu Linux and write it this way. Please look if you like it.
#include <stdio.h>
#include <math.h>
double hypotenuse(double x, double y) {
double z = sqrt(x * x + y * y);
return z;
}
int main(void) {
double b1, b2, counter;
for (counter = 0; counter <= 2; counter++) {
printf("Enter values for two sides: ");
scanf("%lf %lf", &b1, &b2);
printf("%.2f\n", hypotenuse(b1, b2));
}
return 0;
}
Test
$ ./a.out
Enter values for two sides: 1 1.73
2.00
OP's code has some problems:
Key problem: Code should have generated a compiler warning as scanf() is directed to treat &side1 as an int *. Turn on all compiler warnings to save you time. Code used "%d" rather than the matching "%lf" to read a double. Also the return value should be checked to validate input.
double side1, side2, side3, counter;
...
// scanf_s("%d %d", &side1, &side2);
if (scanf_s("%lf %lf", &side1, &side2) != 2) puts("Input error");
size3 is not needed. Call hypotenuse() with 2 arguments. #ghostprgmr
// printf("%.2f\n", hypotenuse(side1, side2, side3));
printf("%.2f\n", hypotenuse(side1, side2));
// double hypotenuse(double x, double y, double z) {
double hypotenuse(double x, double y) {
double z = ...
Minor: Code used "%.2f" to print the value of the hypotenuse. This may be OK with select input values to OP's code, but is a poor choice, in general. If input values are vary small like 0.001 and 0.002, the output will print rounded value of 0.00. With very large values, the result will show many non-important digits as OP found with 130899030500194208680850288727868915862901750748094271410143‌​232.00.
For development and debugging, consider using "%e" ,"%g" or "%a" to see a relevant double.
Note that x * x + y * y is prone to over/under flow, even when mathematically sqrt(x * x + y * y) is in the double range. That is one advantage of the standard function hypot(x,y) as it usually handles those edge cases well.
As a reference for anyone viewing this question:
You don't need to write your own function. Standard C provides functions to calculate the hypotnuse:
7.12.7.3 The hypot functions
Synopsis
#include <math.h>
double hypot(double x, double y);
float hypotf(float x, float y);
long double hypotl(long double x, long double y);
Note that you likely need to link with -lm, though that's not listed explicitly in the function documentation in the C standard nor the latest POSIX documentation. It might be documented elsewhere in the standards.
(Link to C11 [draft] standard - likely to be much longer-lived.)
Use correct format specifiers!
Format Specifier for double is not %d! Rest is fine.
#include <stdio.h>
#include <math.h>
double hypotenuse(double x, double y, double z);
int main(void) {
double side1, side2, side3, counter;
side3 = 1;
for (counter = 0; counter <= 2; counter++) {
printf("Enter values for two sides: ");
scanf("%lf %lf", &side1, &side2);
printf("%.2f\n", hypotenuse(side1, side2, side3));
}
return 0;
}
double hypotenuse(double x, double y, double z) {
x *= x;
y *= y;
z = sqrt(x + y);
return z;
}
Also you could modify it to this:
#include <stdio.h>
#include <math.h>
double hypotenuse(double x, double y);
int main(void) {
double side1, side2, counter;
for (counter = 0; counter <= 2; counter++) {
printf("Enter values for two sides: ");
scanf("%lf %lf", &side1, &side2);
printf("%.2f\n", hypotenuse(side1, side2));
}
return 0;
}
double hypotenuse(double x, double y) {
x *= x;
y *= y;
return sqrt(x + y);
}

How to implement Trapezoidal Integration with Infinite Limits in C?

I am trying to create a c program to integrate sin(x)/sqrt(x) between 0 and Infinity. I am using the trapezium rule by cutting off the end points as the function tends to infinity.
However the total returned is too high and I am not sure why. Here's the code:
#include<math.h>
#include<stdio.h>
double func(double u)
{ double a;
a = ((sin(u))/(sqrt(u)));
return a;}
void main()
{
int i, N;
double sum, u, a, b, h, Fa, Fb, F;
printf("Enter value of N\n");
scanf("%d" ,&N);
a=0.01;
b=1000;
h=(b-a)/(N-1);
sum=0;
F=func(a);
u=a;
for(i=0; i<N; i++)
{
sum=sum+F;
u=u+h;
F=fabs(func(u));
}
Fa=func(a);
Fb=func(b);
sum=sum-(0.5*Fa)-(0.5*Fb);
sum=sum*h;
printf("I: %lf\n", sum);
}
Any thoughts?
working example: http://ideone.com/Xibrov
just remove the fabs in the line F=fabs(func(u));.
and you should use int main(void) and return 0; at the end instead of void main().
Your issue is on the line
F=fabs(func(u));
What you actually want for integrating func is
F=func(u);
In this case I beleive the issue is that fabs(func(u)) is not integrable at infinity, so your algorithm will diverge.

Resources