under/over flow problem?

Q

questions?

I have a problem involves under flow/over flow.

###################################################
# include <stdio.h>
# include <math.h>
# include <stdlib.h>

double rate;
double t;
double u;

int main(){
int i;
double diff;
double rtime;;
t=0.0047590000;
diff=t/10;
rtime=0;
rate=0.00000000000001;

for(i=0;i<10;i++){
printf("real time is:%.50lf and current time:%.50lf\n",t,rtime);
u=(1-exp(-1*rate*rtime))/(1-exp(-1*rate*t));
printf("for the %d th time, u=%.50lf\n",i,u);
rtime=rtime+diff;
}
return 0;
}


************************

The idea is that,u is a monotonically increaseing function of rtime,
as rtime increase from 0 to t, u increase from 0 to 1.

But appearantly it runs into underflow/overflow.

how can I deal with this problem nicely? Roughly, how precise is C
double?

Thanks for comments
 
M

Me

questions? said:
I have a problem involves under flow/over flow.

###################################################
# include <stdio.h>
# include <math.h>
# include <stdlib.h>

double rate;
double t;
double u;

int main(){
int i;
double diff;
double rtime;;
t=0.0047590000;
diff=t/10;
rtime=0;
rate=0.00000000000001;

for(i=0;i<10;i++){
printf("real time is:%.50lf and current time:%.50lf\n",t,rtime);
u=(1-exp(-1*rate*rtime))/(1-exp(-1*rate*t));
printf("for the %d th time, u=%.50lf\n",i,u);
rtime=rtime+diff;
}
return 0;
}


************************

The idea is that,u is a monotonically increaseing function of rtime,
as rtime increase from 0 to t, u increase from 0 to 1.

But appearantly it runs into underflow/overflow.

how can I deal with this problem nicely?

Use <= instead of <.
Roughly, how precise is C double?

Check the standard for the minimum limits, check <limits.h> for your
implementation's limits.
 
E

Eric Sosman

questions? said:
I have a problem involves under flow/over flow.
[code snipped; see up-thread]

Overflow and underflow don't appear to be involved;
your problem appears to arise from finite precision.

Specifically, let's look at the denominator in the
expression for `u':

u = (stuff) / (1 - exp(-1 * rate * t));

Elsewhere in the code, we find that `rate' is 1e-14 and `t' is
4.759e-3, so the argument to exp() is approximately -4.759e-17.
This value is very close to zero, so its exponential will be
very close to one, and the denominator of the fraction will be
very close to zero.

... and that's where precision enters the picture. The
computer has a finite amount of memory, and cannot represent the
value exp(-4.759e-17) with perfect accuracy. (Most computers are
unable even to store the rational number -4.759e-17 with perfect
accuracy, but that's just a distraction at this point.) Instead,
the computer does what humans do: It uses finite approximations
when it calculates, rounding the values to a machine-specific
number of places.

How many places? C requires `double' to provide at least
ten decimal digits' worth of precision; most machines nowadays do
better by providing about fifteen digits. But when rounded to
fifteen places, exp(-4.759e-17) is equal to unity; the departure
from unity is too small to represent. That makes the denominator
equal to `1 - 1', which in turn makes the calculation of `u'
meaningless.
how can I deal with this problem nicely? Roughly, how precise is C
double?

The actual precision of your machine's `double' is described
by the macros defined in <float.h> (not in <limits.h>, as another
poster mistakenly wrote).

There are at least two possibilities for a cure. First, you
could try switching to `long double', which on some machines has
more precision than `double' and might have enough precision to
make something sensible of the calculation. However, `long double'
is only supported meaningfully on a few machines; on many, it is
really just `double' all over again. Consult <float.h> to see
whether `long double' gains any precision on your system.

The second and more promising possibility is to do some math,
and reorganize the calculation so it doesn't require such great
precision. Maybe you can find a power series representation that
doesn't involve subtracting numbers that are very nearly equal, an
almost foolproof (if that's the right word) way to lose precision.

Oh, and by the way: There's no such thing as an "%lf"
conversion specifier for printf(). Use "%f" and its variants --
and don't even begin to hope for fifty decimal places!
 
Q

questions?

Eric said:
questions? said:
I have a problem involves under flow/over flow.
[code snipped; see up-thread]

Overflow and underflow don't appear to be involved;
your problem appears to arise from finite precision.

Specifically, let's look at the denominator in the
expression for `u':

u = (stuff) / (1 - exp(-1 * rate * t));

Elsewhere in the code, we find that `rate' is 1e-14 and `t' is
4.759e-3, so the argument to exp() is approximately -4.759e-17.
This value is very close to zero, so its exponential will be
very close to one, and the denominator of the fraction will be
very close to zero.

... and that's where precision enters the picture. The
computer has a finite amount of memory, and cannot represent the
value exp(-4.759e-17) with perfect accuracy. (Most computers are
unable even to store the rational number -4.759e-17 with perfect
accuracy, but that's just a distraction at this point.) Instead,
the computer does what humans do: It uses finite approximations
when it calculates, rounding the values to a machine-specific
number of places.

How many places? C requires `double' to provide at least
ten decimal digits' worth of precision; most machines nowadays do
better by providing about fifteen digits. But when rounded to
fifteen places, exp(-4.759e-17) is equal to unity; the departure
from unity is too small to represent. That makes the denominator
equal to `1 - 1', which in turn makes the calculation of `u'
meaningless.
how can I deal with this problem nicely? Roughly, how precise is C
double?

The actual precision of your machine's `double' is described
by the macros defined in <float.h> (not in <limits.h>, as another
poster mistakenly wrote).

There are at least two possibilities for a cure. First, you
could try switching to `long double', which on some machines has
more precision than `double' and might have enough precision to
make something sensible of the calculation. However, `long double'
is only supported meaningfully on a few machines; on many, it is
really just `double' all over again. Consult <float.h> to see
whether `long double' gains any precision on your system.

The second and more promising possibility is to do some math,
and reorganize the calculation so it doesn't require such great
precision. Maybe you can find a power series representation that
doesn't involve subtracting numbers that are very nearly equal, an
almost foolproof (if that's the right word) way to lose precision.

Oh, and by the way: There's no such thing as an "%lf"
conversion specifier for printf(). Use "%f" and its variants --
and don't even begin to hope for fifty decimal places!


Thanks for the nice explanation. I at the end, do use an approximation.

Are there systems/implementation that try to create a high precision
enviroment?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top