3

I'm programming a library with multiple instances of long mathematical formulas that sometimes underflow when using doubles. One example could be:

(Exp(-a*a) - Exp(-b*b))*Exp(c)*Exp(d) 

And a,b,c,d also involve some computation of similar type. I can deal with doubles getting this wrong (and return appropriate error message or some analytical bound) but if I don't detect underflow (on the difference of exponentials for instance) it leads to behavior that I can't afford. (Both absolute and relative errors can be massive when this difference clips to zero while other exponentials are very large).

Is there something similar to checked keyword that works for doubles? Is there some way I can implement checks in an assisted way?

Any solution that makes sure it's correct, even one which raises more flags than necessary is good for me.


This question was suggested as a duplicate but 'manually check before every multiplication' is not a particularly usefull solution for me.

Radost
  • 309
  • 3
  • 11
  • Possible duplicate of [How do I detect total loss of precision with Doubles?](https://stackoverflow.com/questions/30726919/how-do-i-detect-total-loss-of-precision-with-doubles) – O. Jones Jun 24 '19 at 22:33
  • @O.Jones In some sense duplicate, but no real solution was given there. Checking literally every multiplication before with non-proceduraly generated code is feasible but I'd rather avoid that for obvious reasons. – Radost Jun 24 '19 at 22:41
  • 1
    C# doesn't throw exceptions for floating underflow. It simply sets the result to zero. So you're stuck with doing your own epsilon work. It's a pain in the neck. As you have discovered. – O. Jones Jun 24 '19 at 22:44
  • If performance and development time are not issues, you can define your own class containing a float and overload operator * and other operations (by performing checks). This way you code will be as clean as before, but it requires some work. –  Jun 24 '19 at 23:09

1 Answers1

3

Is there something similar to checked keyword that works for doubles?

Nope.

Is there some way I can implement checks in an assisted way?

A bad solution: depending on what hardware you are using, the floating point arithmetic chip may set a flag that indicates whether an operation has underflowed. I do not recommend calling into unmanaged code to read that flag off the floating point chip. (I wrote the code to do that in the original Microsoft version of Javascript and it is a pain to get that logic right.)

A better solution: you might consider writing a symbolic logic library. Consider for example what happens if you make your own number type:

struct ExpNumber 
{
  public double Exponent { get; }
  public ExpNumber(double e) => Exponent = e;
  public static ExpNumber operator *(ExpNumber x1, ExpNumber x2) => 
    new ExpNumber(x1.Exponent + x2.Exponent);

And so on. You can define your own addition, subtraction, powers, logarithms, and so on, using the identities you know for powers. Then when it is time to realize the thing back to a double, you can implement that using whatever stable algorithm that avoid underflow that you prefer.

The problem is that doubles intentionally trade off a decrease in representational power and accuracy for a massive increase in speed. If you need to accurately represent numbers smaller than 10e-200, doubles are not for you; they were designed to solve problems in physics computation, and there are no physical quantities that small.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067