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
Related
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.
When I run my code, for Y I am consistently getting the value -2147483648, regardless of what value y was fed into my equation.
Here is my code.
#define MAX 1000
#define EQ(y) ((2*(pow(y, 4)))+1)
int check(int value);
int main()
{
int i, y, x;
for(y = 1; y < MAX; y++)
{
i = EQ(y);
if(check(i))
printf("combination found: x = %d, y = %d", sqrt(i), y);
}
}
int check(int value)
{
int x = sqrt(value);
if ((x*x) == value)
return 1;
else
{
return 0;
}
}
After reviewing my code, I realized my problem was with my "int x = sqrt(value)". Aside from the problem with the "value" variable being an int, of course, a bogus value was still being returned due to the fact that the purpose of check is to evaluate whether or not (2*(pow(y, 4)))+1) returned a perfect whole square for any given value of y, and this was not possible due to variable x in check(double value) being datatype integer.
UPDATE: I rewrote my code as follows. I still don't get any correct returns
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*
* the solution I implemented basically involved dropping x from the equation, solving for y, checking to see if it has a
* perfect square root. if it does, then x = the squareroot of y in the function EQ.
* original problem: for equation x^2 - 2y^4 + 1 = 0, find all possible solutions up to arbitrary maximum
*/
#define MAX 100000
#define EQ(g) (((pow(g, 4.0)))+1)
int check(double value);
int main()
{
int y, x;
double i;
for(y = 1; y < MAX; y++)
{
i = EQ(y);
if(x = check(i) > 0)
printf("combination found: x = %d, y = %d\n", y, x);
}
}
int check(double value)
{
double x = sqrt(value);
int n = (int) x;
printf("%d\n%f\n%f\n", n*n, value, x);
if (n*n == value)
return n*n;
else
return 0;
}
Read the comments are the top of my code, and the purpose for this selection should be pretty obvious.
You don't have a prototype for double pow(double, double); so the compiler implicitly assumes its signature is int pow(int, int);. Not good!
The solution is to #include the appropriate header at the top of your .c file.
#include <math.h>
Make sure you enable warnings, and if they're already enabled, pay attention to them! Your compiler should warn you about the missing prototype. (It should also spit out a similar warning for printf.)
pow() returns double and you are using integer i to store the return value.
Due to type promotion during expression evaluation the expression:
((2*(pow(y, 4)))+1)
will give a double value and you are storing this in integer type which will give unexpected results.
In reference to your updated question, this line:
if(x = check(i) > 0)
needs to be parenthesized:
if((x = check(i)) > 0)
This is the declaration of pow:
double pow(double x, double y)
Which means it operates in double. By using int instead, variable y is overflowing.
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;
}
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.
Little bit of a 2 parter. First of all im trying to do this in all c. First of all I'll go ahead and post my program
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
#include <string.h>
double f(double x);
void Trap(double a, double b, int n, double* integral_p);
int main(int argc, char* argv[]) {
double integral=0.0; //Integral Result
double a=6, b=10; //Left and Right Points
int n; //Number of Trapezoids (Higher=more accurate)
int degree;
if (argc != 3) {
printf("Error: Invalid Command Line arguements, format:./trapezoid N filename");
exit(0);
}
n = atoi(argv[2]);
FILE *fp = fopen( argv[1], "r" );
# pragma omp parallel
Trap(a, b, n, &integral);
printf("With n = %d trapezoids....\n", n);
printf("of the integral from %f to %f = %.15e\n",a, b, integral);
return 0;
}
double f(double x) {
double return_val;
return_val = pow(3.0*x,5)+pow(2.5*x,4)+pow(-1.5*x,3)+pow(0*x,2)+pow(1.7*x,1)+4;
return return_val;
}
void Trap(double a, double b, int n, double* integral_p) {
double h, x, my_integral;
double local_a, local_b;
int i, local_n;
int my_rank = omp_get_thread_num();
int thread_count = omp_get_num_threads();
h = (b-a)/n;
local_n = n/thread_count;
local_a = a + my_rank*local_n*h;
local_b = local_a + local_n*h;
my_integral = (f(local_a) + f(local_b))/2.0;
for (i = 1; i <= local_n-1; i++) {
x = local_a + i*h;
my_integral += f(x);
}
my_integral = my_integral*h;
# pragma omp critical
*integral_p += my_integral;
}
As you can see, it calculates trapezoidal rule given an interval.
First of all it DOES work, if you hardcode the values and the function. But I need to read from a file in the format of
5
3.0 2.5 -1.5 0.0 1.7 4.0
6 10
Which means:
It is of degree 5 (no more than 50 ever)
3.0x^5 +2.5x^4 −1.5x^3 +1.7x+4 is the polynomial (we skip ^2 since it's 0)
and the Interval is from 6 to 10
My main concern is the f(x) function which I have hardcoded. I have NO IDEA how to make it take up to 50 besides literally typing out 50 POWS and reading in the values to see what they could be.......Anyone else have any ideas perhaps?
Also what would be the best way to read in the file? fgetc? Im not really sure when it comes to reading in C input (especially since everything i read in is an INT, is there some way to convert them?)
For a large degree polynomial, would something like this work?
double f(double x, double coeff[], int nCoeff)
{
double return_val = 0.0;
int exponent = nCoeff-1;
int i;
for(i=0; i<nCoeff-1; ++i, --exponent)
{
return_val = pow(coeff[i]*x, exponent) + return_val;
}
/* add on the final constant, 4, in our example */
return return_val + coeff[nCoeff-1];
}
In your example, you would call it like:
sampleCall()
{
double coefficients[] = {3.0, 2.5, -1.5, 0, 1.7, 4};
/* This expresses 3x^5 + 2.5x^4 + (-1.5x)^3 + 0x^2 + 1.7x + 4 */
my_integral = f(x, coefficients, 6);
}
By passing an array of coefficients (the exponents are assumed), you don't have to deal with variadic arguments. The hardest part is constructing the array, and that is pretty simple.
It should go without saying, if you put the coefficients array and number-of-coefficients into global variables, then the signature of f(x) doesn't need to change:
double f(double x)
{
// access glbl_coeff and glbl_NumOfCoeffs, instead of parameters
}
For you f() function consider making it variadic (varargs is another name)
http://www.gnu.org/s/libc/manual/html_node/Variadic-Functions.html
This way you could pass the function 1 arg telling it how many "pows" you want, with each susequent argument being a double value. Is this what you are asking for with the f() function part of your question?