c function returning nan instead of double - c

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.

Related

Why is my power function not working properly here?

I've tried changing variable types but this is still not working.
double power(double a, long long b){
while(b>1){
a *= a;
b--;
}
return a;
}
Your code won't run properly when b>2 because when you're doing a = a*a; the second time it won't be a^3 but a^4 and the next time it will be a^8 and so on.
The right code would be something like this below:
double power(double a, long long b){
double k = 1;
while(b>0){
k *= a;
b--;
}
return k;
}
You're changing a on every iteration. Say you call it like power(2, 3).
First you do 2 * 2 and assign this to a, which becomes 4.
Next iteration, you'll do again a * a which is 4 * 4. Just keep the result in a variable and don't change the arguments:
double power(double a, long long b){
double r = a;
while(b>1){
r *= a;
b--;
}
return r;
}
you are changing the variable a and it courses the defects. what you can do instead is
double power(double base, double exp)
{
double result = 1;
for(int i = 0; i < exp; i++)
{
result *= base;
}
return result;
}

Getting wrong square-root estimation

I have written a program in C which is calculating for me the square root with the heron procedure. x is my number, r is estimated value and steps are steps. I want to output the difference between the exact value and the value obtained by the heron method. But it seems that my function is not correct. For my calculated value I get no value. Can anyone help me?
#include <stdio.h>
#include <math.h>
int heron (x, r, steps)
{
int k = 0;
double xold, xnew;
double rel_error = 1.0;
while(k <= steps && rel_error > 1e-4) {
++k;
xnew = .5 * (xold + x / xold);
rel_error = (xnew - xold) / xnew;
if(rel_error < 0)
rel_error = -rel_error;
xold = xnew;
}
printf("exact value: %.10f\n", sqrt(x));
return (xnew);
}
int main()
{
int x=4, r=10, steps=50;
printf("%f\n", heron(x, r, steps));
return 0;
}
Change int heron (x, r, steps) to double heron(double x, double r, int steps). You need to declare the types of the parameters, and the function works with floating-point values, so it ought to return float or double, not int, and x and r should be double.
Change double xold , xnew; to double xold = r, xnew;. xold must be initialized before it is used.
Change return sqrt(x); to return xold; to return the value that the function calculated.
With this prefix
int heron (x, r, steps)
{
your function is a function that takes an integer x, another integer r, and a third integer steps. Indeed, it also returns an integer.
The algorithm you describe can be implemented in this way:
#include <stdio.h>
#include <math.h>
double heron(double x, double err)
{
double a = x, b = 1.0;
while (a - b > err) {
a = (a + b)/2.0; /* arithmetic mean */
b = x / a; /* approx to geometric mean */
}
return a; /* or b, depending if you want a value in excess or in defect */
}
int main()
{
printf("heron(2.0, 1.0E-10) = %.10f\n", heron(2.0, 1.0E-10));
printf("sqrt(2.0) = %.10f\n", sqrt(2.0));
}
and that will work.
Read about function parameter type definitions in one of the many references of the C programming languages, e.g. "The C programming language" from Brian Kernighan & Dennis Ritchie, for reference.
$ ./heron
heron(2.0, 1.0E-10) = 1.4142135624
sqrt(2.0) = 1.4142135624
$ _

Calculating $\sqrt[3]{x}$ with Babylonian method

Consider my attempt to implement the Babylonian method in C:
int sqrt3(int x) {
double abs_err = 1.0;
double xold = x;
double xnew = 0;
while(abs_err > 1e-8) {
xnew = (2 * xold + x/(xold* xold))/3;
abs_err= xnew-xold;
if (abs_err < 0) abs_err = -abs_err;
xold=xnew;
}
return xnew;
}
int main() {
int a;
scanf("%d", &a);
printf(" Result is: %f",sqrt3(a));
return 0;
}
Result is for x=27: 0.0000?
Where is my mistake?
While the function returns an int, that value is printed with the wrong format specifier, %f instead of %d.
Change the signature (and the name, if I may) into something like this
double cube_root(double x) { ... }
Or change the format specifier, if you really want an int.
Following the explanation from tutorialspoint, which states, that the basic idea is to implement the Newton Raphson method for solving nonlinear equations, IMHO, the code below displays this fact more clearly. Since there is already an accepted answer, I add this answer just for future reference.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
double rootCube( double a)
{
double x = a;
double y = 1.0;
const double precision = 0.0000001;
while(fabs(x-y) > precision)
{
x = (x + y) / 2.0;
y = a / x / x;
}
return x;
}
int main(int argc, const char* argv[])
{
if(argc > 1)
{
double a =
strtod(argv[1],NULL);
printf("cubeRoot(%f) = %f\n", a, rootCube(a));
}
return 0;
}
Here, in contrast to the original code of the question, it is more obvious, that x and y are the bounds, which are being improved until a sufficiently accurate solution is found.
With modification of the line in the while block, where y is being updated, this code can also be used to solve similar equations. For finding the square root, for example, this line would look like this: y = a / x.

commenting a printf statement stops output

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

recursive segmentation fault

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;
}

Resources