Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this evaluate to False?

Tags:

c#

unity3d

I'm a bit confused and can't explain this behaviour:

Vector3 k = new Vector3(Mathf.NegativeInfinity, Mathf.NegativeInfinity,Mathf.NegativeInfinity);
Debug.Log(k==k); // evaluates to False

though

Debug.Log(Mathf.Mathf.NegativeInfinity == Mathf.Mathf.NegativeInfinity)
// evaluates to True as expected

I'm using Unity Version 5.3.5f1.

like image 863
f.b. Avatar asked Jul 21 '16 16:07

f.b.


2 Answers

From Unity's documentation, == returns "true for vectors that are really close to being equal". However this implementation produces problems when the Vector is initialized with negative infinity for x,y,z.

Let's take a look at how == is defined for Vector3:

public static bool operator == (Vector3 lhs, Vector3 rhs) {
    return Vector3.SqrMagnitude (lhs - rhs) < 9.999999E-11;
}

Before doing SqrMagnitude, it will first perform lhs - rhs, so let's see how - is defined:

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

This is fine for normal numbers, however, since a.x, b.x...etc. are Mathf.NegativeInfinity, the subtraction will result in NaN. Now when it does sqrMagnitude:

public float sqrMagnitude {
    get {
        return this.x * this.x + this.y * this.y + this.z * this.z;
    }
}

This will also return NaN.

From the docs, we note the following:

  • If either operand is NaN, the result is false for all operators except !=, for which the result is true.

Therefore, when we go back to this code:

return Vector3.SqrMagnitude (lhs - rhs) < 9.999999E-11;

It simplifies to return NaN < 9.999999E-11; which will return False as stated in the docs.


Also, the reason why Debug.Log(Mathf.Mathf.NegativeInfinity == Mathf.Mathf.NegativeInfinity) behaves as expected is documented here.

  • Negative and positive zeros are considered equal.
  • A negative infinity is considered less than all other values, but equal to another negative infinity.
  • A positive infinity is considered greater than all other values, but equal to another positive infinity.
like image 186
Bill Avatar answered Sep 20 '22 16:09

Bill


Equality operator can be or can't be implemented. It's just an implementation detail of a given type. Or it can be also wrongly implemented.

Even when all properties from a given class may equal when comparing two references, if == and != aren't overloaded, or their implementation is wrong, it may end in unexpected results like yours.

For example:

public class A 
{
     public static operator bool ==(A left, A right) => false;
     public static operator bool !=(A left, A right) => false;
}

A a = new A();

bool equals = a == a; // false
bool notEquals = a != a // false

BTW:

bool referenceEquals = ReferenceEquals(a, a); // TRUE!
like image 32
Matías Fidemraizer Avatar answered Sep 22 '22 16:09

Matías Fidemraizer