0

I am trying to code an iterative function which takes an initial

double t = /*formula 1*/;

and then computes

for (auto i = 0; i < bigNumber; ++i)
{
    temp = /*formula 2*/;
    t = t*temp;
}

This works fine, except in the cases where the initial t is so small that C++ automatically sets it equal to zero (it is NOT actually supposed to be zero).

Then of course t will forever remain zero since we multiply it by itself, and that's the problem.

I tried solving this by setting t equal to some very small, but non-zero, number in case C++ had set it to zero, but this doesn't work, because then, I end up with the opposite problem, as t eventually blows up, once we have iterated it enough times.

How do I solve this problem?

Possibly worth mentioning:

The first formula (formula 1) involves stuff like exp(-verybignumber) and the second formula involves stuff like pow(i, -1), meaning it becomes very small with higher iterations.

Acorn
  • 24,970
  • 5
  • 40
  • 69
Make
  • 345
  • 2
  • 6
  • 1
    [`std::numeric_limits::epsilon`](https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon) might come in handy. – πάντα ῥεῖ Oct 14 '18 at 21:37
  • 1
    it's not `C++` that sets the variable to `0`. It's the logic of floating point math. Related: https://stackoverflow.com/questions/588004/is-floating-point-math-broken. You could try implementing your own BigDecimal class, or use a premade one from external libraries – Fureeish Oct 14 '18 at 21:37
  • 4
    Rethink your logic. Possible directions include: Can you rearrange the order you do computations to avoid the over/under flow? Can you work in logarithms? – 1201ProgramAlarm Oct 14 '18 at 21:39
  • " second formula involves stuff like pow(i, -1)" --> best to post that function. The first iteration `i=0` results in `pow(0, -1)` -> infinity. – chux - Reinstate Monica Oct 15 '18 at 04:52

1 Answers1

1

Floating-point arithmetic isn't trivial, as you just discovered. This is not really related to C++, but to the IEEE 754 standard.

One of the things you need to need to ensure is that you stay within the normal numbers. That is, ensure your values throughout your computation do not get too small or too large.

In some cases, this is easy and maybe rescaling the input data is enough. In other cases, maybe you have to rethink your equations (steps) to avoid this.

Sometimes you can simply get away using a bigger type, e.g. long double or even __float128 (quad, check libquadmath).

Other solutions are to employ arbitrary-precision numbers (use a library like GMP and MPFR; do not attempt to do it yourself as a beginner) or even symbolic computation. It all depends on what performance you require.

Note that there are many other pitfalls when dealing with floating-point arithmetic.

Acorn
  • 24,970
  • 5
  • 40
  • 69
  • Note that IEEE 754 is not required by C++ (ISO 14882). C++ lets a lot of those details to be implementation & platform defined. That being said, many platforms implement IEEE 754, or something very close to it. – Eljay Oct 14 '18 at 23:11
  • @Eljay I haven't said it is required by the C++ standard, though. Also, for this answer, it does not really matter which FP standard is used, because any math based on FP will suffer from the same issues. I could remove the mention, though; but I think telling OP which is the name of the one he/she is most likely using is good for him/her. – Acorn Oct 15 '18 at 10:07