> 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
>
>

Reply via email to