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.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With