Tech Off Thread

10 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Possible bug in C# math?

Back to Forum: Tech Off
  • User profile image
    BrianPeiris

    The following expression should return true.

    (1133 * 6.0 / 1133) == (1133 * (6.0 / 1133))

    Although the math is sound in, C# disagrees.

    1133 * 6.0 / 1133 returns 6.0

    whereas

    1133 * (6.0 / 1133) returns 6.0000000000000009

    Is this a bug, or am I supposed to expect some rounding error when I divide first?

  • User profile image
    Maurits

    That's just how floating-point math works.  Using == or != is rarely correct for floats or doubles.

  • User profile image
    BrianPeiris

    It's not just that the expressions aren't equal,
    using 1133*(6.0/1133), which returns 6.0000000000000009, (which is mathematically incorrect) in further expressions will result in further errors.

  • User profile image
    Maurits

    It's because 6.0 / 1133 is being rounded up at the last digit stored in the float.  Then when you multiply by 1133 the rounding shows itself as the extra .00..09.

    The same thing happens in base 10.  Consider 6 * (2 / 3) on a calculator with a finite number of digits:

    2 / 3 = 0.66...67
    6 * 0.66...67 = 4.00...02

  • User profile image
    BrianPeiris

    hmmm, yes I see how that works, I guess it can't be helped then.

  • User profile image
    W3bbo

    BrianPeiris wrote:
    hmmm, yes I see how that works, I guess it can't be helped then.


    It can't, but it involves you implementing an "Infinite Prescision" engine. The Windows calculator had this flaw until recently, so you're not alone.

    There's an example written in C here.

  • User profile image
    AndyC
  • User profile image
    BrianPeiris

    Thanks for the links W3bbo and AndyC.
    Infinite Precision isn't really necessary for my current application and I've found a work-around for the FP problem, but definitely good resources to add to my bookmarks.

  • User profile image
    Maurits

    You could use macros:

    #define CLOSE_ENOUGH 0.00001
    #define FLOAT_EQUAL(f, g) (abs((f) - (g)) <= CLOSE_ENOUGH)
    #define FLOAT_NOT_EQUAL(f, g) (!FLOAT_EQUAL(f, g))

  • User profile image
    AndyC

    I sometimes wonder why the comparison operators for floating point values isn't just defined to take this into account. Surely that would eliminate a whole raft of unnecessary bugs in a much cleaner, more OO way.

    You could still have a float.CloseEnough static property to adjust the accuracy if needed.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.