开发者

Class with overridden equals method not returning true for SOME objects that are equal

I have a vector class that has it's Equals(object obj) method overridden so that I can compare them.

public class Vector3f
{
    public float x,y,z;
    public Vector3f(float x, float y, float z)
    {
       this.x = x;
       this.y = y;
       this.z = z;
    }

    public static Vector3f operator +(Vector3f a, Vector3f b) {
        return new Vector3f(a.x + b.x, a.y + b.y, a.z + b.z);
    }

    public static Vector3f operator -开发者_运维百科(Vector3f a, Vector3f b) {
        return new Vector3f(a.x - b.x, a.y - b.y, a.z - b.z);
    }
    public override bool Equals(object obj)
    {
        Vector3f other = (Vector3f)obj;
        return x == other.x && y == other.y && z == other.z;
    }

    public override string ToString()
    {
        return String.Format("<{0},{1},{2}>",x,y,z);
    }
}

The plus operator works as expected in my unit tests. However, when I subtract two vectors it says they are not equal

Test 'RTTests.Testies.vector_subtraction_works' failed: 
Expected: <<1.1,0.1,0.1>>
But was:  <<1.1,0.1,0.1>>
Testies.cs(60,0): at RTTests.Testies.vector_sub_works()

I'm not sure why the comparison is working for addition and not subtraction especially since the output values are identical in both cases?

EDIT: My tests for this

    [Test]
    public void vector_addition_works()
    {
        Vector3f v1 = new Vector3f(1.0f, 1.0f, 1.0f);
        Vector3f v2 = new Vector3f(1.6f, 3.2f, 4.7f);

        Vector3f expected = new Vector3f(2.6f, 4.2f, 5.7f);
        Vector3f actual = v1 + v2;

        Assert.AreEqual(actual, expected);
    }

    [Test]
    public void vector_sub_works()
    {
        Vector3f v1 = new Vector3f(1.1f, 1.1f, 1.1f);
        Vector3f v2 = new Vector3f(0.0f, 1.0f, 1.0f);

        Vector3f expected = new Vector3f(1.1f, 0.1f, 0.1f);
        Vector3f actual = v1 - v2;

        Assert.AreEqual(actual, expected);
    }


Your problem must be a rounding/truncation error. It happens all the time with floating point operations, specially subtraction. When you test for equality, instead of a==b, use a-b < SmallConstant. You could also try using double precision or Decimal, although truncation errors will eventually return, but you might make them less common.


If you debug the app you will see the following:

1.1f - 1.0f = 0.100000024

0.1 can't be represented in binary exactly. It would be like trying to write out 1/3 in base 10 exactly, you cant do it because it goes on forever. There is another similar question that explains this and links to some code to print out what the actual value of the float is


You are probably seeing the problem because you are using floats. Floats by their nature are not precise. Unless you need to use float for some reason, I would change my class to use Decimals instead.

Hope this helps.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜