Complex number equals method
I'm making a complex number class in Java like this:
public class Complex {
public final double real, imag;
public Complex(double real, double imag) {
this.real = real;
this.imag = imag;
}
... methods for arithmetic follow ...
}
I implemented the equals method like this:
@Override
public boolean equals(Object obj) {
if (obj instanceof Complex) {
Complex other = (Complex)obj;
return (
this.real == other.real &&
this.imag == other.imag
);
}
return false;
}
But if you override equals, you're supposed to override hashCode too. One
of the rules is:
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce the
same integer result.
Comparing floats and doubles with == does a numeric comparison, so +0.0 ==
-0.0 and NaN values are inequal to everything including themselves. So I
tried implementing the hashCode method to match the equals method like
this:
@Override
public int hashCode() {
long real = Double.doubleToLongBits(this.real); // harmonize NaN bit
patterns
long imag = Double.doubleToLongBits(this.imag);
if (real == 1L << 63) real = 0; // convert -0.0 to +0.0
if (imag == 1L << 63) imag = 0;
long h = real ^ imag;
return (int)h ^ (int)(h >>> 32);
}
But then I realized that this would work strangely in a hash map if either
field is NaN, because this.equals(this) will always be false, but maybe
that's not incorrect. On the other hand, I could do what Double and Float
do, where the equals methods compare +0.0 != -0.0, but still harmonize the
different NaN bit patterns, and let NaN == NaN, so then I get:
@Override
public boolean equals(Object obj) {
if (obj instanceof Complex) {
Complex other = (Complex)obj;
return (
Double.doubleToLongBits(this.real) ==
Double.doubleToLongBits(other.real) &&
Double.doubleToLongBits(this.imag) ==
Double.doubleToLongBits(other.imag)
);
}
return false;
}
@Override
public int hashCode() {
long h = (
Double.doubleToLongBits(real) +
Double.doubleToLongBits(imag)
);
return (int)h ^ (int)(h >>> 32);
}
But if I do that then my complex numbers don't behave like real numbers,
where +0.0 == -0.0. But I don't really need to put my Complex numbers in
hash maps anyway -- I just want to do the right thing, follow best
practices, etc. And now I'm just confused. Can anyone advise me on the
best way to proceed?
No comments:
Post a Comment