> This is not the case for: > > EpsilonDoublePrecisionContext > Vector1D > Vector2D > Vector3D > SphericalCoordinates > PolarCoordinates Indeed. I tried to analyze it but get to know you need to treat -0.0 equals 0.0 here, thus I don't think I can simply change it to Double.compare.
And yes, hashCode is why I suggest you consider about the migration. If two objects are equals to each other while having different hashCode, that would be weird. Alex Herbert <alex.d.herb...@gmail.com> 于2020年7月4日周六 下午8:57写道: > Xeno raised the use of Double.compare to be used to test for equality of > floating point values instead of ==. > > This should only be done if -0.0 and 0.0 are considered different. If this > is the case then the accompanying hashCode value should not use > Double.hashCode since when two objects are equal they must have the same > hash code. > > This is not the case for: > > EpsilonDoublePrecisionContext > Vector1D > Vector2D > Vector3D > SphericalCoordinates > PolarCoordinates > > When some of the numbers are 0.0 (or -0.0) as they use == for equality > then their hash codes are different. In the cases of: > > AffineTransformMatrix2D > AffineTransformMatrix3D > AxisAngleSequence > > When the doubles are 1 ulp apart they are equal as they use > Precision.equals for equality but they will have a different hash code. > (Note that AffineTransformMatrix1D does not use Precision.equals but > Double.compare == 0 so is fine.) > > I think I have found all the cases of a broken hashCode but a search > should be made for Double.hashCode and check all the hashCode and equals > implementations are consistent. > > > If Precision.equals is to be used in the equals method then it will > require some changes to have a correct hashCode implementation. There are 3 > options: > > 1. Document the inconsistency > > In this case the class should be documented as being inconsistent with the > hashCode contract, something like: > > <p>Note: This class has a hashCode that is inconsistent with equals. > > > 2. Switch to binary equality > > Provide a binary equality in equals and then a second method for equals > using a precision context. > > > 3. Smarter hashCode functions > > For the case where 0.0 == -0.0 is to be used in equals then the hash code > can be produced using: > > Double.hashCode(0.0 - x); > > Since: > > +0.0 - +0.0 = +0.0 > +0.0 - -0.0 = +0.0 > > All other non-Nan values will have the sign inverted for the argument to > hashCode and NaN will remain NaN. > > For the cases using Precision, IIUC the Precision.equals is always used > with an allowed 1 ulp difference. So the following would work: > > Long.hashCode(Double.doubleToLongBits(0.0 - x) >>> 2); > > This should discard the least significant 2 bits thus any differences of 1 > ulp will be discarded from the number. Note I’ve not tested this approach. > > Alex > >