Reputation: 279
I'm trying to find the Trapezoidal Rule estimation of the Goempertz function and use it to measure the difference between the life expectancy for a 50 year old smoker and a 50 year old non smoker but my code has been giving me crap answers.
The Goempertz function for a person at age 50 can be coded as:
exp((-b/log(c))*pow(c,50)*(pow(c,t)-1))
where b
and c
are constants and we need to integrate it from 0 to infinity (a very large number) to get the life expectancy.
For a non-smoker, the life expectancy can be calculated with: constants b = 0.0005, c = 1.07. And for a smoker, the life expectancy can be calculated with constants b = 0.0010, c = 1.07.
const double A = 0; // lower limit of integration
const double B = 1000000000000; // Upper limit to represent infinity
const int N = 10000; //# number of steps of the approximation
double g(double b, double c, double t) //
{//b and c are constants, t is the variable of integration.
return exp((-b/log(c))*pow(c,50)*(pow(c,t)-1));
}
double trapezoidal(double Bconst, double Cconst)
{
double deltaX = (B-A)/N; //The "horizontal height" of each tiny trapezoid
double innerTrap = 0; //innerTrap is summation of terms inside Trapezoidal rule
for (int i = 0; i <= N; i++)
{
double xvalue;
if (i == 0) // at the beginning, evaluate function of innerTrap at x0=A
{
xvalue = A;
}
else if (i == N) //at the end, evaluate function at xN=B
{
xvalue = B;
}
else //in the middle terms, evaluate function at xi=x0+i(dX)
{
xvalue = A + i * deltaX;
}
if ((i == 0) || (i == N)) //coefficient is 1 at beginning and end
{
innerTrap = innerTrap + 1*g(Bconst, Cconst, xvalue);
}
else // for all other terms in the middle, has coefficient 2
{
innerTrap = innerTrap + 2*g(Bconst, Cconst, xvalue);
}
}
return (deltaX/2)*innerTrap;
}
int main()
{
cout << "years 50 year old nonsmoker lives: " << trapezoidal(0.0005,1.07) << endl;
cout << "years 50 year old smoker lives: " << trapezoidal(0.0010,1.07) << endl;
cout << "difference between life expectancies: " << trapezoidal(0.0005,1.07)-trapezoidal(0.0010,1.07) << endl;
return 0;
}
Upvotes: 3
Views: 126
Reputation: 5070
As I understand you made a mistake with the constants B
and N
. B
- the number of years that a person can live with a certain probability and N
is integration step. Therefore B
should be relatively small (<100, because the probability that a person will live 50+100 years or more is extremely small) and N
should be as large as possible. You can use following code to solve your task
const double A = 0; // lower limit of integration
const double B = 100; // Upper limit to represent infinity
const int N = 1000000; //# number of steps of the approximation
double g(double b, double c, double t) //
{//b and c are constants, t is the variable of integration.
return exp((-b/log(c))*pow(c,50)*(pow(c,t)-1));
}
double trapezoidal(double Bconst, double Cconst)
{
double deltaX = (B-A)/double(N); //The "horizontal height" of each tiny trapezoid
double innerTrap = 0; //innerTrap is summation of terms inside Trapezoidal rule
double xvalue = A + deltaX/2;
for (int i = 0; i < N; i++)
{
xvalue += deltaX;
innerTrap += g(Bconst, Cconst, xvalue);
}
return deltaX*innerTrap;
}
int main()
{
double smk = trapezoidal(0.0010,1.07);
double nonsmk = trapezoidal(0.0005,1.07);
cout << "years 50 year old nonsmoker lives: " << nonsmk << endl;
cout << "years 50 year old smoker lives: " << smk << endl;
cout << "difference between life expectancies: " << nonsmk-smk << endl;
return 0;
}
Upvotes: 1
Reputation: 6204
The problem lies in your choice of end x-coordinate and the number of slices you sum the area over:
const double A = 0;
const double B = 1000000000000;
const int N = 10000;
double deltaX = (B-A) / N; //100 million!
When you do a discrete integration like this you want your deltaX
to be small compared to how the function changes. I would guess the Goempertz function changes quite a lot between 0 and 100 million.
To fix it simply make the two changes:
const double B = 100;
const int N = 10000000;
This makes deltaX == 0.00001
and seems to give good results (21.2 and 14.8). Making B
larger doesn't change the final answer much (if at all) as the function value at this range is essentially 0.
If you'd like to be able to figure out how to choose good values of B
and N
the process is roughly like this:
B
find the value of x
where the function result is small enough (or the function change in is small enough) to ignore. This can be tricky for periodic or complex functions.N
value and compute your result. Increase N
by a factor of 2 (or something) until the result converges to the desired accuracy.B
is valid by increasing it and see if the change in result is less than your desired accuracy.For example, my choices of B
and N
were very conservative. These could be reduced as low as B = 50
and N = 10
and still give the same result to 3 significant figures.
Upvotes: 1