C# Maths gives wrong results!

后端 未结 4 903
迷失自我
迷失自我 2020-12-12 01:53

I understand the principle behind this problem but it\'s giving me a headache to think that this is going on throughout my application and I need to find as solution.

<
相关标签:
4条回答
  • 2020-12-12 01:59

    Instead of using Round to round the number, you could use some function you write yourself which uses a small epsilon when rounding to allow for the error. That's the answer you want.

    The answer you don't want, but I'm going to give anyway, is that if you want precision, and since you're dealing with money judging by your example you probably do, you should not be using binary floating point maths. Binary floating point is inherently inaccurate and some numbers just can't be represented correctly. Using Decimal, which does base-10 floating point, would be a much better approach everywhere and will avoid you making costly mistakes with your doubles.

    0 讨论(0)
  • 2020-12-12 02:02

    If you're looking for exact representations of values which are naturally decimal, you will need to replace double with decimal everywhere. You're simply using the wrong datatype. If you'd been using short everywhere for integers and then found out that you needed to cope with larger values than that supports, what would you do? It's the same deal.

    However, you should really try to understand what's going on to start with... why Value doesn't equal exactly 141.1, for example.

    I have two articles on this:

    • Binary floating point in .NET
    • Decimal floating point in .NET
    0 讨论(0)
  • 2020-12-12 02:05

    You should use decimal – that's what it's for.

    The behaviour of floating point arithmetic? That's just what it does. It has limited finite precision. Not all numbers are exactly representable. In fact, there are an infinite number of real valued numbers, and only a finite number can be representable. The key to decimal, for this application, is that it uses a base 10 representation – double uses base 2.

    0 讨论(0)
  • 2020-12-12 02:19

    After spending most of the morning trying to replace every instance of a 'double' to 'decimal' and realising I was fighting a losing battle, I had another look at my Round function. This may be useful to those who can't implement the proper solution:

    public static double Round(double dbl, int decimals) {            
            return (double)Math.Round((decimal)dbl, decimals, MidpointRounding.AwayFromZero);
        }
    

    By first casting the value to a decimal, and then calling Math.Round, this will return the 'correct' value.

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