Numerical Differentiation - c

How can I calculate the numerical second derivative of a function involving an exponential and a singularity at infinity. Unfortunately, the numerical derivative by Ridder's methods provided in "Numerical Recipes in C" can only calculate the first derivative (It requires analytical expression of the function beforehand.) Furthermore I have tried Chebyshev approximation and differentiating the function afterwards but the values given were way off the actual values. I have also tried some finite difference algorithms provided in a mathematical paper yet they were error prone too. The function is e^(x/2) / x^2. I would appreciate any help on the matter.
Thanks in advance
Latest Edit: The issue was solved the FADBAD libraries available in C++ did an extremely good job. They are available via http://www.fadbad.com/fadbad.html
EDIT:
// The compilation command used is given below
// gcc Q3.c nrutil.c DFRIDR.c -lm -o Q3
#include <stdio.h>
#include <math.h>
#include "nr.h"
#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a
* plot. It also calculates the maximum and minimum of the func
* at given points and its first and second numerical derivative.
*/
float func(float x)
{
return exp(x / 2) / pow(x, 2);
}
int main(void)
{
FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
int i; // Declaring our loop variable
float x, y, min, max, err, nd1, nd2;
// Define the initial value of the func to be the minimum
min = func(0);
for(i = 0; x < LIM1 ; i++)
{
x = i / pre; // There is a singularity at x = 0
y = func(x);
if(y < min)
min = y;
fprintf(fp, "%f \t %f \n", x, y);
}
fprintf(fp, "\n\n");
max = 0;
for(i = 0, x = a; x < b; i++)
{
x = a + i / pre;
y = func(x);
nd1 = dfridr(func, x, 0.1, &err);
//nd2 = dfridr((*func), x, 0.1, &err);
fprintf(fp, "%f \t %f \t %f \t %f \n", x, y, nd1);
if(y > max)
max = y;
}
fprintf(fp2, "The minimum value of f(x) is %f when x is between 0 and 20. \n", min);
fprintf(fp2, "The maximum value of f(x) is %f when x is between -5 and 5. \n", max);
fclose(fp);
fclose(fp2);
return 0;
}
EDIT: Chebyshev
// The compilation command used is given below
//gcc Q3.c nrutil.c CHEBEV.c CHEBFT.c CHDER.c -lm -o Q3
#include <stdio.h>
#include <math.h>
#include "nr.h"
#define NVAL 150 // Degree of Chebyshev polynomial
#define LIM1 20.0
#define a -5.0
#define b 5.0
#define pre 100.0 // This defines the pre
/* This file calculates the func at given points, makes a
* plot. It also calculates the maximum and minimum of the func
* at given points and its first and second numerical derivative.
*/
float func(float x)
{
return exp(x / 2) / pow(x, 2);
}
int main(void)
{
FILE *fp = fopen("Q3data.dat", "w+"), *fp2 = fopen("Q3results.dat", "w+");
int i; // Declaring our loop variable
float x, y, min, max;
float nd1, nd2, c[NVAL], cder[NVAL], cder2[NVAL];
// Define the initial value of the func to be the minimum
min = func(0);
for(i = 0; x < LIM1 ; i++)
{
x = i / pre; // There is a singularity at x = 0
y = func(x);
if(y < min)
min = y;
fprintf(fp, "%f \t %f \n", x, y);
}
fprintf(fp, "\n\n");
max = 0;
// We make a Chebyshev approximation to our function our interval of interest
// The purpose is to calculate the derivatives easily
chebft(a,b,c,NVAL,func);
//Evaluate the derivatives
chder(a,b,c,cder,NVAL); // First order derivative
chder(a,b,cder,cder2,NVAL); // Second order derivative
for(i = 0, x = a; x < b; i++)
{
x = a + i / pre;
y = func(x);
nd1 = chebev(a,b,cder,NVAL,x);
nd2 = chebev(a,b,cder2,NVAL,x);
fprintf(fp, "%f \t %f \t %f \t %f \n", x, y, nd1, nd2);
if(y > max)
max = y;
}
fprintf(fp2, "The minimum value of f(x) is %f when x is between 0 and 20. \n", min);
fprintf(fp2, "The maximum value of f(x) is %f when x is between -5 and 5. \n", max);
fclose(fp);
fclose(fp2);
return 0;
}

That function is differentiable so using a numeric method is likely not the best. The second derivative is:
6*exp(x/2)/(x^4)-2*exp(x/2)/x^3 + exp(x/2)/(4*x^2)
The above can be simplified of course to speed up computation. Edit: had original formula wrong the first time.

If you want a 100% numeric approach then look at the numerical recipes for a cublic spline interpolation (Charter 3.3). It will give you the 2rd derivative at any location.
call spline() with x and y values to return the 2nd derivatives in y2. The second derivative varies linearly within each interval. So if for example you have
x y y2
0 10 -30
2 5 -15
4 -5 -10
then the 2nd derivative at x=1 is y2=-22.5 which is in-between -30 and -15.
you can also make a new splint() function to return the 2nd derivative a*y2a[i]+b*y2a[i+1]

Related

find square root with Newton using integers

In this program, I'm trying to calculate the square root with the newton equation 1/2(x+a/x) just using integers. So if I repeat this equation at least 10 times, it should divide the number by 1000 and give an approximate value of the square root of a/1000. This is the code:
int main (){
int32_t a, x; //integers a and x
float root;
do{
scanf ("%d", &a); // get value of a from the user
if (a < 1000 ){ // if chosen number is less than 1000 the programm ends.
break;
}
x = ((float) a / 1000); //starting value of x is a / 1000;
for (int i = 0; i < 50;i++)
{
root = ((float) x * (float) x + a/1000) / ((float)2*x); // convert int to float //through casting
x = (float)root; // refresh the value of x to be the root of the last value.
}
printf ("%f\n", (float)root);
}while (1);
return 0;
}
so if I calculate the square root of 2000, it should give back the square root of 2(1.414..), but it just gives an approximate value: 1.50000
How can I correct this using integers and casting them with float?
thanks
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char * *argv, char * *envp) {
int32_t a, x; //integers a and x
float root;
do {
scanf ("%d", &a); // get value of a from the user
if (a < 1000) { // if chosen number is less than 1000 the program ends.
break;
}
x = (int32_t)((float) a / 1000.0f); //starting value of x is a / 1000;
for (int i = 0; i < 1000; i++) {
// Fixed formula based on (x+a/x)/2
root = ((float)x + (((float)a) / (float)x)) / 2.0f;
//Below, wrong old formula
//root = ((float) x * (float) x + a / 1000) / ((float) 2 * x); // convert int to float //through casting
x = (int32_t) root; // refresh the value of x to be the root of the last value.
}
printf ("%f\n", root);
} while (1);
return (EXIT_SUCCESS);
}
The iterates of x = (x + a / x) / 2 for a = 2000000 and x0 = 1000 (all integer variables) are 1500, 1416 and 1414. Then 200000000 gives 14142 and so on.

How to use exp and sqrt properties correctly

-use double precision
-use sqrt() and exponential function exp()
-use * to compute the square
-do not use pow()
I am getting values they are just not anything as to what I expected. I tried making them all signed but it didn't change anything and I've tried printing out with 12 decimal places and nothing seems to be working.I have linked the math library and defined it as well.
double normal(double x, double sigma, double mu)
{
double func = 1.0/(sigma * sqrt(2.0*M_PI));
double raise = 1.0/2.0*((x-mu)/sigma);
double func1 = func * exp(raise);
double comp_func = (func1 * func1);
return comp_func;
}
int main(void)
{
// create two constant variables for μ and σ
const double sigma, mu;
//create a variable for x - only dynamic variable in equation
unsigned int x;
//create a variable for N values of x to use for loop
int no_x;
//scaniing value into mu
printf("Enter mean u: ");
scanf("%lf", &mu);
//scanning value into sigma
printf("Enter standard deviation: ");
scanf("%lf", &sigma);
//if sigma = 0 then exit
if(sigma == 0)
{
printf("error you entered: 0");
exit(0);
}
//storing number of x values in no_x
printf("Number of x values: ");
scanf("%d", &no_x);
//the for loop where i am calling function normal N times
for(int i = 1; i <= no_x; i++)
{
//printing i for the counter in prompted x values
printf("x value %d : ", i);
// scanning in x
scanf("%lf", &x);
x = normal(x,sigma,mu);
printf("f(x) = : %lf.12", x);
printf("\n");
}
return 0;
}
C:>.\a.exe
Enter mean u: 3.489
Enter std dev s: 1.203
Number of x values: 3
x value 1: 3.4
f(X) = 0.330716549275
x value 2: -3.4
f(X) = 0.000000025104
x value 3: 4
f(X) = 0.303015189801
But this is what I am receiving
C:\Csource>a.exe
Enter mean u: 3.489
Enter standard deviation: 1.203
Number of x values: 3
x value 1 : 3.4
f(x) = : 15086080.000000
x value 2 : -3.4
f(x) = : 15086080.000000
x value 3 : 4
f(x) = : 1610612736.000000
Insert these lines:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
Change:
const double sigma, mu;
to:
double sigma, mu;
Change:
unsigned int x;
to:
double x;
Replace the definition of the normal function with:
double normal(double x, double sigma, double mu)
{
double func = 1.0/(sigma * sqrt(2.0*M_PI));
double t = (x-mu)/sigma;
return func * exp(-t*t/2);
}
#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
#include<math.h>
#include<stdio.h>
#include <stdlib.h>
double normal(double x, double sigma, double mu)
{
double func = 1.0/(sigma * sqrt(2.0*M_PI));
double t = (x-mu)/sigma;
return func * exp((-0.5*t)* t);
}
I Finally got this code above working after tweaking with it literally all day lol, C math can be rather tricky, thank you for the help above as well.

Write c code to evaluate the integral between 0 and y of (x^2)(e^-x^2)dx using Simpson's rule (use a fixed number of 20,000 steps)

Second part of Q: Then solve the integral between 0 and y of (x^2)(e^(-x^2))dx=0.1 for y using bracketing and bisection.
Here's what I have done so far:
#include <stdio.h>
#include <math.h>
double f(double x, double y);
int main(void) {
int i, steps;
double a, b, y, h, m, lower, upper, x, simp, val;
/*
* Integrate (x^2)(e^(-x^2)) from 0 to y
*/
steps = 20000;
a = 0;
b = y;
h= (b-a)/steps;
/*
* now apply Simpson's rule. Note that the steps should be even.
*/
simp = -f(a, y);
x = a;
for (i =0; i < steps; i += 2) {
simp += 2.0*f(x,y)+4.0*f(x+h, y);
x += 2*h;
}
simp += f(b, y);
simp *= h/3.0;
/*
* print out the answer
*/
printf("The integral from 0 to y with respect to x by Simpson's Rule is %f\n", simp);
/*
* Now we need to bracket and bisect to find y
*/
lower = 0;
/*
* Lower bound is from turning point
*/
upper = 100;
/*
*Upper value given.
*/
while (upper - lower > 10E-10){
m = (lower + upper)/2;
val = f(m, y);
if (val >=0)
upper = m;
if (val <=0)
lower = m;
}
m = (lower + upper)/2;
printf("The value for y is: %lf\n", m);
return 0;
}
double f(double x, double y) {
return pow(x,2)*exp(pow(-x,2))-0.1;
}
Output: The integral from 0 to y with respect to x by Simpson's Rule is -0.000000
The value for y is: 0.302120
It runs but doesn't do exactly what I need it to do. I need to be able to continue working with the integral once I've used 0 and y as the limits. I can't do this. Then continue on and solve for y. It gives me a value for y but is not the same one I get if i solve using online calculators. Also, the output gave zero for the integral even when I changed the equation to be integrated to x^2. Can anyone help explain in as simple terms as possible?

Trouble calculating perimeter of a polygon from reading x, y coordinate input into arrays

Having trouble with program that calculates the perimeter of a polygon from an input of (x,y) coordinates. I need to use arrays and I'm not very confident with them. Mostly having trouble with reading the values into the array from a .txt file (using <) and also how to use the last point and first point to close off the polygon.
The input is:
3 1.0 2.0 1.0 5.0 4.0 5.0
5 1.0 2.0 4.0 5.0 7.8 3.5 5.0 0.4 1.0 0.4
4 1.0 0.4 0.4 0.4 0.4 3.6 1.0 3.6
0
Where the first number in each row indicates the number of points (npoints) and then followed by the coordinates themselves which are in clear groups of two i.e. (x,y).
Each new row indicates a new polygon needing to be read.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_PTS 100
#define MAX_POLYS 100
#define END_INPUT 0
double
getDistance(int npoints, double x[], double y[]) {
double distance = 0.0;
for (int i = 0; i < npoints; ++i) {
int j =; // I'm stuck here
distance = sqrt((x[i]-x[j]) * (x[i]-x[j]) + (y[i]-y[j]) *(y[i]-y[j]));
}
return distance;
}
int
main(int argc, char *argv[]) {
int npoints, iteration = 0;
double x[MAX_PTS], y[MAX_PTS];
double perimeter = 0.0;
if (npoints == END_INPUT){
scanf("%d", &npoints);
// start with 0 value of parameter.
for (iteration = 0; iteration < npoints; ++iteration) {
scanf("%lf %lf", &(x[iteration]), &(y[iteration]));
// take input for new-point.
// for next iteration, new-point would be first-point in getDistance
}
perimeter += getDistance(npoints, x, y);
perimeter += getDistance(); // stuck here
// need to add the perimeter
// need to complete the polygon with last-edge joining the last-point
// with initial-point but not sure how to access array
printf("perimeter = %2.2f m\n", perimeter);
}
return 0;
}
The output for the first polygon should be 10.24m
If anyone could give me a hand that would be great, I'm quite stumped
You were almost there. After adding the file input, just a few tweaks here and there. Most importantly, how to make the array point wrap back to the front.
#include <stdio.h>
#include <math.h>
#define MAX_PTS 100
double getDistance(int npoints, double x[], double y[]) {
double distance = 0.0, dx, dy;
int i;
for (i = 0; i < npoints; ++i) {
dx = x[(i+1) % npoints] - x[i]; // wrap the index
dy = y[(i+1) % npoints] - y[i];
distance += sqrt(dx * dx + dy * dy); // accumaulate
}
return distance;
}
int main(int argc, char *argv[]) {
int npoints, point;
double x[MAX_PTS], y[MAX_PTS];
double perimeter;
FILE *fp;
if (argc < 2) {
printf("No file name supplied\n");
return 1;
}
if ((fp = fopen(argv[1], "rt")) == NULL) {
printf("Error opening file\n");
return 1;
}
while (1) {
if (1 != fscanf(fp, "%d", &npoints)) { // check result
printf("Error reading number of sides\n");
return 1;
}
if (npoints == 0)
break; // end of data
if (npoints < 3 || npoints > MAX_PTS) { // check range
printf("Illegal number of sides %d\n", npoints);
return 1;
}
for (point = 0; point < npoints; ++point) {
if (2 != fscanf(fp, "%lf %lf", &x[point], &y[point])) { // check result
printf("Error reading coordinates of %d-sided polygon\n", npoints);
return 1;
}
}
perimeter = getDistance(npoints, x, y); // include args
printf("perimeter = %2.2f\n", perimeter);
}
fclose(fp);
return 0;
}
Program output:
>test polydata.txt
perimeter = 10.24
perimeter = 18.11
perimeter = 7.60
Get rid of the test of npoints == END_INPUT in main(). It serves no purpose and, since npoints is uninitialised, gives undefined behaviour.
As to the question you asked, assuming the points represent a polygon with no edges crossing over, the distance will be the sum of distances between adjacent points (0->1, 1->2, ....., npoint-2 -> npoints-1, npoints-1 -> 0).
The only special one of these is the last. Other than the last, the distance is being computed between point i to point i + 1.
That suggests j is i+1 for i = 0 to npoints-2. Then, for i == npoints-1, j will be equal to 0.
Writing code to implement that is trivial.

Problem finding the local maximum of a function in C

I'm designing an algorithm to define a simple method able to find the local maximum of a function f (x) given in an interval [a, b]
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141592653
float funtion_(float a, float x){
float result=0;
result = a * (sin (PI*x));
return result;
}
int main (){
double A = 4.875; //average of the digits of the identification card
double a = 0.0, b =1.0; //maximum and minimum values of the interval [a, b]
double h=0;
double N;
double Max, x;
double sin_;
double inf;
printf ("input the minux value: ");
scanf ("%lf", &inf);
printf ("input the N value: ");
scanf ("%lf", &N);
h= (b-a)/N;
printf("h = %lf\n", h);
x=a-h;
Max = -inf;
do {
x = x+h;
sin_ = funtion_(A, x);
if (sin_>=Max){
Max = sin_;
}
}while (x==b);
printf ("Maximum value: %lf.5", Max);
return 0;
}
The algorithm implements the function f (x) = A * sin (pi * x), where A is the average of the digits of my ID, and inf variable is assigned a number sufficiently greater than the values ​​reached by the function in the interval [a, b] = [0.1].
The algorithm must find the local maximum of the function but it is the maximum returns always zero. do not understand why. What problem may be the logic of my solution?, this problem can be solved by this simple algorithm or some optimization by backtracking is necessary ? Thanks for your responses.
Several problems with this code; probably the most glaring is:
int a = 0, b = 1;
float Max, x;
/* ... */
do {
/* ... */
} while (x == b);
You cannot compare an int and a float for equality. It might work once in a great while due to dumb luck :) but you cannot expect this code to function reliably.
I strongly recommend changing all your int variables to double, all your float variables to double, and all the scanf(3) and printf(3) calls to match. While you can combine different primitive number types in one program, and even in one expression or statement, subtle differences in execution will take you hours to discover.
Furthermore, comparing floating point formats for equality is almost never a good idea. Instead, compare the difference between two numbers to a epsilon value:
if (fabs(a-b) < 0.001)
/* consider them equal */
You might want to scale your epsilon so that it matches the scale of your problem; since float really only supports about seven digits of precision, this comparison wouldn't work well:
if (fabsf(123456789 - 123456789.1) < 0.5)
/* oops! fabsf(3) used to force float */
/* and float can't tell the difference */
You might want to find a good introduction to numerical analysis. (Incidentally, one of my favorite classes back in school. :)
update
The core of the problem is your while(x == b). I fixed that and a few smaller problems, and this code seems to work:
#include
#include
#include
#define PI 3.141592653
float funtion_(float a, float x)
{
float result = 0;
result = a * (sin(PI * x));
return result;
}
int main()
{
float A = 4.875; //average of the digits of the identification card
float a = 0.0, b = 1.0; //maximum and minimum values of the interval [a, b]
float h = 0;
float N;
float Max, x;
float sin_;
float inf;
printf("\ninput the inf value: ");
scanf("%f", &inf);
printf("\ninput the N value: ");
scanf("%f", &N);
h = (b - a) / N;
x = a - h;
Max = -inf;
do {
x = x + h;
sin_ = funtion_(A, x);
if (sin_ >= Max) {
Max = sin_;
printf("\n new Max: %f found at A: %f x: %f\n", Max, A, x);
}
} while (x < b);
printf("Maximum value: %.5f\n", Max);
return 0;
}
Running this program with some small inputs:
$ ./localmax
input the inf value: 1
input the N value: 10
new Max: 0.000000 found at A: 4.875000 x: 0.000000
new Max: 1.506458 found at A: 4.875000 x: 0.100000
new Max: 2.865453 found at A: 4.875000 x: 0.200000
new Max: 3.943958 found at A: 4.875000 x: 0.300000
new Max: 4.636401 found at A: 4.875000 x: 0.400000
new Max: 4.875000 found at A: 4.875000 x: 0.500000
Maximum value: 4.87500
$
You are doing your calculations, in particular the initialisation of h, with integer arithmetic. So in the statement:
h = (b-a) / N;
a, b, and N are all integers so the expression is evaluated as an integer expression, and then converted to a float for assignment to h. You will probably find that the value of h is zero. Try adding the following line after the calculation of h:
printf("h = %f\n", h);
After you've fixed that by doing the calculations with floating point, you need to fix your while loop. The condition x = b is definitely not what you want (I noticed it was originally x == b before your formatting edit, but that's not right either).
Should the while condition be: while(x <= b)
while (x = b);
There is no way to exit the loop. b is always 1.

Resources