# under/over flow problem?

Discussion in 'C Programming' started by questions?, Apr 7, 2006.

1. ### questions?Guest

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?

questions?, Apr 7, 2006

2. ### MeGuest

questions? wrote:
> 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.

Me, Apr 7, 2006

3. ### Eric SosmanGuest

questions? wrote:

> 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!

--
Eric Sosman

Eric Sosman, Apr 7, 2006
4. ### questions?Guest

Eric Sosman wrote:
> questions? wrote:
>
> > 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!
>
> --
> Eric Sosman
>

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?

questions?, Apr 13, 2006