Can anyone explain this strange behavior with signed floats in C#?

前端 未结 11 2015
别跟我提以往
别跟我提以往 2020-12-07 07:17

Here is the example with comments:

class Program
{
    // first version of structure
    public struct D1
    {
        public double d;
        public int f         


        
相关标签:
11条回答
  • 2020-12-07 07:45

    Half an answer:

    Reflector tells us that ValueType.Equals() does something like this:

    if (CanCompareBits(this))
        return FastEqualsCheck(this, obj);
    else
        // Use reflection to step through each member and call .Equals() on each one.
    

    Unfortunately both CanCompareBits() and FastEquals() (both static methods) are extern ([MethodImpl(MethodImplOptions.InternalCall)]) and have no source available.

    Back to guessing why one case can be compared by bits, and the other cannot (alignment issues maybe?)

    0 讨论(0)
  • 2020-12-07 07:46

    …what do you think about this?

    Always override Equals and GetHashCode on value types. It will be fast and correct.

    0 讨论(0)
  • 2020-12-07 07:50

    I found the answer at http://blogs.msdn.com/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx.

    The core piece is the source comment on CanCompareBits, which ValueType.Equals uses to determine whether to use memcmp-style comparison:

    The comment of CanCompareBits says "Return true if the valuetype does not contain pointer and is tightly packed". And FastEqualsCheck use "memcmp" to speed up the comparison.

    The author goes on to state exactly the problem described by the OP:

    Imagine you have a structure which only contains a float. What will occur if one contains +0.0, and the other contains -0.0? They should be the same, but the underlying binary representation are different. If you nest other structure which override the Equals method, that optimization will also fail.

    0 讨论(0)
  • 2020-12-07 07:55

    Just an update for this 10 years old bug: it has been fixed (Disclaimer: I'm the author of this PR) in .NET Core which would be probably released in .NET Core 2.1.0.

    The blog post explained the bug and how I fixed it.

    0 讨论(0)
  • 2020-12-07 07:56

    It does give true for me, with Mono's gmcs 2.4.2.3.

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