Dealing with floating point errors in .NET

后端 未结 3 787
醉酒成梦
醉酒成梦 2020-12-18 00:07

I\'m working on a scientific computation & visualization project in C#/.NET, and we use doubles to represent all the physical quantities. Since floating-po

相关标签:
3条回答
  • 2020-12-18 00:49

    This is not a problem unique to .NET. The strategy to reduce loss of precision is to re-order calculations so that you multiply large quantities times small quantities and add/subtract similiar sized quantities (without changing the nature of the calculation, obviously).

    In your example, rather than multiply 5 large quantities together and then divide by 5 large quantities, re-order to divide each large quantity by one of the divisors, and then multiply these 5 partial results.

    Of interest? (if you haven't already read): What Every Computer Scientist Should Know About Floating-Point Arithmetic

    0 讨论(0)
  • 2020-12-18 00:51

    Your best answer is always better algorithms, of course. But it seems to me that if your values aren't all within a couple of orders of magnitude of 1, the using a fixed epsilon is not a good strategy. What you want to do instead is to insure that the values are equal to within some reasonable precision.

    // are values equal to within 12 (or so) digits of precision?
    //
    bool ApproxEquals(double d1, double d2) {
        return Math.Abs(d1 - d2) < (Math.Abs(d1) * 1e-12);
    }
    

    If this were C++, then you could also pull some tricks to compare the mantissa and exponent separately, but I can't think of any way to do this safely in unmanged code.

    0 讨论(0)
  • 2020-12-18 01:01

    Due to the way real numbers are typically represented, You can do this in C (and probably in unsafe C#):

    if (llabs(*(long long)&x - *(long long)&y) <= EPSILON) {
        // Close enough
    }
    

    This is obviously non-portable and probably a bad idea, but it has the significant advantage of scale-independence. That is, EPSILON can be some small constant like 1, 10 or 100 (depending on your desired tolerance), and it will handle proportional rounding errors correctly regardless of the exponent.

    Disclaimer: This is my own private invention, and has not been vetted by anyone with a clue (like, say, a mathematician with a background in discrete arithmetic).

    0 讨论(0)
提交回复
热议问题