So I wrote a header that uses recursion to compute several mathematical functions. Including the cosine function and exponential function( e^x). Now the cosine functions works just fine but e^x produces a segmentation fault even though both use the same recursive procedure. So here is the code from the header file I created "c_math.h":
#define PI 3.141592
static unsigned int n;
................
uint32_t Factorial(unsigned int p)
{
if(p==0){
return(1);
}else if(p>0){
return p*Factorial(p-1);
}
};
double EXP(double x)
{
int N = n;
double F = (double)Factorial(n);
if(n==0){
return (1.0);
}else{
return EXP(x)+(Pow(x,N)/F);
}
}
double cosine(double x)
{
int N = (2*n);
double F = (double)(Factorial(2*n)*(-1^n));
if(n==0){
return(1.0);
}else if(n==1){
return 1+(Pow(x,2)/2);
}else if(n>1){
return cosine(x)+(Pow(x,N)/F);
}
};
double cos(double x){
bool halt = false;
double COS;
n = 0;
while(halt==false){
int N = (2*n);
double F = (double)(Factorial(2*n)*(-1^n));
COS = cosine(x);
if(abs(Pow(x,N)/F)<=0.0001){
halt = true;
}else{
n++;
}
}
return COS;
}
double e(double x){
bool halt = false;
double E;
n = 0;
while(halt==false){
int N = n;
double F = (double)(Factorial(n));
E = EXP(x);
if(abs(Pow(x,N)/F)<=0.0001){
halt = true;
}else{
n++;
}
}
return E;
}
The .c file with the main function:
include <stdio.h>
#include <cmath.h>
int main()
{
printf("\n");
printf("cos(2.2) = %4.6f\n",cos(2.2));
printf("\n");
printf("e(2.2) = %4.6f\n",e(2.2));
printf("\n");
}
After I compile it and then execute from the terminal prompt, the output looks like this:
zermacr0yd#DALEK /usr/lib/gcc/x86_64-linux-gnu/4.7.3/include $ ./mathtest
cos(2.2) = -0.588501
Segmentation fault
So as you can see the Cosine function works as it should but e^x produces a segmentation fault. Now the function e^x is strictly increasing for x > 0 and strictly decreasing for x < 0, but mathematically the power series should converge for all values of x which means that eventually when the series index n becomes high enough, the value of the nth term should fall below 0.0001. So what is going on here?
All your functions are using a variable n which I'm assuming is declared globally but only defined locally in e. You should provide a local definition of n for each function: int n = 0;.
Unix or the POSIX standard defines a tool named bc, which is a (very basic) multi-precision command line calculator. With it comes a numerical library that provides explicit implementations for exp, cos and sin and others. Study that for efficient, precise algorithms. The manpage, for instance at
http://www.gnu.org/software/bc/manual/html_mono/bc.html#SEC18
contains the implementation for exp(x) starting at the line define e(x).
Basically, for the Taylor series to work you first have to reduce the argument as close to zero as possible. bc mainly uses the technique of halving-and-squaring. For sin and cos the periodicity and symmetry can also be used.
The full bc library can be found at
http://code.metager.de/source/xref/gnu/bc/1.06/bc/libmath.b
double EXP(double x) {
/* other code that doesn't change x */
if(n==0) {
return 1.0;
} else {
return EXP(x) + /* other code */;
}
}
Let's say we want to calculate EXP(2).
EXP starts running, gets to the second return statement, and calls EXP(2) again.
Which calls EXP(2) again.
Which calls EXP(2) again.
Which calls EXP(2) again. Etc.
Recursion only works if the function eventually stops recursing.
A no-nonsense implementation of the cosine Taylor series is
#include<stdio.h>
#include<math.h>
double cos_taylor(double x) {
double mxx=-x*x, a=1, c=0;
unsigned int k=1;
while(1+a!=1) {
c+=a;
a*=mxx/(k++)/(k++);
}
return c;
}
int main() {
double x;
for(x=-0.5; x<3.2; x+=0.1)
printf(" x=%10.7f \t math.cos(x)=%20.16g \t taylor.cos(x)=%20.16g\n",
x, cos(x), cos_taylor(x));
return 0;
}
Related
I am trying to write C code to perform some mathematical calculation. I was using a printf statement to check the print the variable. When I was done with the code, and I was getting the desired output, I commented the line out. However, after doing that, I am not getting any output. Uncommenting the line gets the desired output back.
#include <stdio.h>
#include <math.h>
#define M 1000
const double eps = 1.110223e-16;
const double delta = 1.110223e-16;
void bisection(double (*fn)(double), double a, double b) {
//Bisection algorithm
double w, c, u, v, e;
int i;
u = (*fn)(a);
v = (*fn)(b);
e = b - a;
if(signbit(u) == signbit(v)) {
printf("Stopping due to same sign\n");
return;
}
for(i = 0; i < M; i++) {
printf("%d\n", i);
e = e / 2;
c = a + e;
w = (*fn)(c);
//Stopping conditions epsilon and delta
if(abs(e) <= eps || abs(w) <= delta) {
printf("Root is %e\n", c);
return;
}
if(signbit(w) == signbit(u)) {
//Means that root lies in [c,b]
a = c;
u = w;
} else {
// Means root lies in [a, b]
b = c;
v = w;
}
}
}
double problem_a(double x) {
return (pow(x, -1) - tan(x));
}
int main(int argc, char *argv[])
{
double (*fn)(double);
fn = &problem_a;
bisection(fn, 0.0 + eps, M_PI/2 - eps);
return 0;
}
The output I am getting is: Root is 7.853982e-01
I get no output if I comment the file.
I am using the gcc compiler version 4.8.3
What can be a possible explanation for this behaviour?
You are calling abs without a declaration! This means that the compiler doesn't know the expected types of any arguments.
You pass a double argument to abs (which expects an int). This invokes undefined behaviour, which means anything can happen. And in your case it does, since you get different results if you add an unrelated printf.
You can fix the undefined behaviour by adding a declaration for abs. Indeed, if you #include <stdlib.h> the problem with the printf goes away.
This won't make your program correct, though. As pointed out by #cremno in the comments, you should use fabs to get the absolute value of a double.
So, modify the line that calls abs like this:
if(fabs(e) <= eps || fabs(w) <= delta) {
Running the modified program prints out
0
1
2
3
<skipping a few lines>
51
52
Root is 8.603336e-01
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)
We're taking up numerical methods in my programming class and the first algorithm introduced to us was the bisection method for root finding. Here's my attempt at implementing it using recursion:
#include <math.h>
#include <stdio.h>
#define tolerance 0.00001
double my_function(double z){
double answer = 5*pow(z,2) + 5*z - 2;
return answer;
}
double bisection(double (*fxn)(double),double a, double b){
double m = ((a+b)/2);
if (fabs(b-a) < tolerance){
double root = a;
printf("value of a is %lf\n",root);
return a;
}
else if (fxn(m) > 0){
b = m;
}
else if (fxn(m) < 0){
a = m;
}
bisection(my_function, a, b);
}
int main(){
double g = 0.01;
double z = 1;
double x = bisection(my_function,g,z);
printf("root is %lf\n",x);
return 0;
}
and here is the output:
value of a is 0.306225
root is nan
The root is correct (slightly off, but within the tolerance level) but somewhere in between returning the value and printing it, it somehow turns into NaN. I'm stumped. What am I doing wrong?
You are not returning from the recursive call. Change the last statement in bisection to
return bisection(my_function, a, b);
My first guess:
in the section
if (fabs(b-a) < tolerance){
double root = a;
printf("value of a is %lf\n",root);
return a;
}
You return a instead of root. Try returning root and see if that helps.
Im trying to make a program that calculates out a math equation, Im getting stuck on how i generate a random number from 0.00 to 1.00 and store it in a variable a.
this is my code so far, im stuck to how now take that number and store it for future use. I need to store that random number in a, and hten use it in a loop, and then generate a new random number and use it in the 2nd cycle of the loop.
EDIT
this is what i have been working on now, it is suppose to calculate the number of times a random number is inside the area, count it, and then devide by the number of times run, but im not getting any output
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
void initrand(void)
{
srand(time(0));
}
float randfloat(void)
{
return rand()/(float)RAND_MAX;
}
int main(void)
{
int n = 10;
float x;
float y;
float pi = 3.1415;
float rootxy;
initrand();
int z = 0;
int inside = 0;
x = randfloat();
y = randfloat();
float area = 0.25 * pi;
float calculatedpi;
rootxy = sqrt(pow(x,2) + (pow(y,2)));
while (z < n){
if (rootxy > area) {
inside++;
z++;
}
else{
return 0;
}
calculatedpi = (inside/n);
}
printf("%f", calculatedpi);
}
There are a few issues with your code:
You shouldn't use nested functions. Some compilers support them as an extension but it's not standard. Define randfloat and initrand outside main
The function initrand does too little. Why not call srand((time(0)); from main ?
Your initrand function is declared as returning a double but it doesn't return anything (and the way it's named it shouldn't). If you need to use such a function, why not make it return void ?
You should rarely use float. Why not use double ?
That said, you can do this to store that random value:
double randdouble()
{
return rand()/((double)RAND_MAX + 1);
}
int main()
{
double x = randdouble();
/* ... */
}
I think you want something like this:
#include <stdlib.h>
#include <time.h>
void initrand(void)
{
srand(time(0));
}
float randfloat(void)
{
return rand()/(float)RAND_MAX;
}
int main(void)
{
initrand();
float a = randfloat();
return 0;
}
You can't nest functions like in some other languages.
You had non-matching parentheses in the initrand function.
I fixed the declarations of your functions, use void when there are no parameters, initrand doesn't return anything.
Your division by RAND_MAX+1 was a little messed up. Simply divide by RAND_MAX and the result will be in the closed interval [0,1]. And the syntax for the conversion to float was not quite right.
If you want to get random double numbers in a specified range you can use this function
// Return a random double from a to b
double randomDouble(double a, double b)
{
return = ( rand() / ( (double)RAND_MAX + 1.0))
* (b - a) + a;
}
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Okay, so I have tried everything I could think of and haven't been able to figure out how to get this program working. I have tested all the functions used in the main, but included them anyway just in case there is some bug in them. More than likely though, I believe my mistake is in the main.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.14159265359
double int_power(double x, int e);
int main()
{
int my_factorial(int n);
double my_sine_taylor(double x);
double my_sine(double x);
double mod_two_pi(double x);
double get_double(void);
void safeGetString(char arr[], int limit)
char arr[255];
double x,y,ans;
printf("Enter a number: ");
safeGetString(arr[255],255);
my_sine(mod_two_pi(get_double()));
printf("The sine is %f \n", ans);
return 0;
}
/*
int_power should compute x^e, where x is a double and e is an integer.
*/
double int_power(double x, int e)
{
int i = 0;
double ans = 1;
while(i <= e)
{
ans = ans*x;
i++;
}
return ans;
}
/*
my_factorial will find the factorial of n
*/
int my_factorial(int n)
{
int i = n;
int ans = 1;
while(i > 0)
{
ans = ans*i;
i = i-1;
}
return ans;
}
/*
my_sine_taylor computes the approxmiation
of sin(x) using the taylor series up through x^11/11!
*/
double my_sine_taylor(double x)
{
return x - int_power(x,3)/my_factorial(3) + int_power(x,5)/my_factorial(5) -
int_power(x,7)/my_factorial(7) + int_power(x,9)/my_factorial(9) -
int_power(x,11)/my_factorial(11);
}
/*
my_sine(x) should return a very good approximation of sin(x).
It should first reduce x mod 2pi and then map the result into the
upper right quadrant (where the taylor approximation is quite accurate).
Finally, it should use my_sine_taylor to compute the answer.
*/
double my_sine(double x)
{
double ans;
if (x >= 0 && x <= PI/2){
ans = my_sine_taylor(x);
} else if (x > PI/2 && x <= PI){
x=PI-x;
ans = my_sine_taylor(x);
} else if (x > PI && x <= 3*(PI/2)){
x = x-PI;
ans = -(my_sine_taylor(x));
} else {
x=2*PI-x;
ans = -(my_sine_taylor(x));
}
}
/*
mod_two_pi(x) should return the remainder when x
is divided by 2*pi. This reduces values like
17pi/2 down to pi/2
*/
double mod_two_pi(double x)
{
int y;
y = floor(x/(2*PI));
x = x - 2*PI*y;
return x;
}
/*
get_double and safeGetString are used to get floating point
input from the user
*/
double get_double(void)
{
double x;
char arr[255];
x=atof(arr);
}
void safeGetString(char arr[], int limit)
{
int c, i;
i = 0;
c = getchar();
while (c != '\n'){
if (i < limit -1){
arr[i] = c;
i++;
}
c = getchar();
}
arr[i] = '\0';
}
oh my... where to begin?
Let's see...
You have this function:
double get_double(void)
{
double x;
char arr[255];
x=atof(arr);
}
Which you call like this:
my_sine(mod_two_pi(get_double()));
So you're not sending it anything, but you're expecting to get some meaningful value. Basically, arr[255] is not initialized, so it holds garbage. You're taking this garbage and converting it to a float with atof, but that doesn't do anything.
If I had to guess, I'd say that this is what's really breaking your program. The rest of what I wrote below is just commentary.
For some reason, you're declaring all of these functions inside your main. I don't think this should break anything, but it sure is bad coding style.
my_sine_taylor calculates using a 6-element taylor approximation of the sine. Are you sure you need that accuracy? 11! is pretty large, and certain numbers to the 11th power can also be pretty large. You may be introducing unnecessary rounding or overflow errors with this.