Feature suggestion: Add static equals methods to Float and Double

Ulf Adams ulfjack at google.com
Tue Jan 8 09:16:36 UTC 2019

Technically, another option would be to have Java standardize a meaning,
and I take it you're not mentioning that because of the performance

On Tue, Jan 8, 2019 at 2:37 AM John Rose <john.r.rose at oracle.com> wrote:

> As I think you expect, isSubstitutible(x,y) will mean that x and y are
> equivalent
> for all practical purposes.  One hard question is nailing down what are
> "all practical purposes".  Certainly it's unfair to flip a coin while
> evaluating
> x and y separately, and claim that a distinct outcome proves a difference.
> What about viewing the bits of x and y using the Unsafe API?  That's
> unfair also, since it opens the door to implementation-dependent behavior
> which might detect a difference (an irrelevant difference) between x and y.
> Now, floatToRawIntBits can detect differences between NaNs which
> have different numeric codes.  Are two such NaNs substitutable or not?
> The evidence in favor:
>  - They become equivalent when boxed in a Float, and Float claims to
>   be an all-purpose box for float values.
>  - The extra information produced by floatToRawIntBits is implementation
>   specific, and in particular processor dependent.
>  - Joe Darcy suggested to me that some processors, like x87, may
>   perturb NaN bits (turning off the "signalling" bit, for example), even
>   if the float value is simply bound to a parameter.  This means that
>   the operand to floatToRawIntBits *might*, in compiled code, possibly
>   have *some* of its bits perturbed.  (Thanks, Joe, for that and similar
>   hair-raising stories.)
>  - The previous point implies that compiled code and interpreted code
>   might, in the same JVM instance, produce different results on the
>   same argument.  That is quite implementation specific indeed!
> The evidence against:
>  - The existing standard API point floatToRawIntBits is not going away.
>   So the isSubstitutable API point must document that floatToRawIntBits
>   has the processor-dependent ability to conjure up different bits for
>   x and y.  Maybe it should be called isAlmostSubstitutable??
> The right trade-off here, I think, is to align isSubstitutable with
> Float::equals
> and simply increase the warnings on floatToRawIntBits, that this method
> can produce platform-specific results in an unpredictable way, and that
> in particular it can produce distinct answers for otherwise substitutable
> results.
> I also suggested to Dr. Deprecator (Stuart Marks) that floatToRawIntBits
> might be a candidate for deprecation; he said it would be a lot of expense
> for relatively little benefit.  I think at least the javadoc for
> floatToRawIntBits
> should not speak so confidently, as it does, of "preserving Not-a-Number
> (NaN) values", as if these values were something that had a stable
> semantics, as if they could somehow carry application information.
> More background (thanks again to Joe):  The NaN bits don't have a standard
> format.  Different CPUs can (and often do) disagree on which bits
> mean what, and how standard arithmetic operations consume and produce
> them.  There is apparently no agreed standard NaN pattern, although
> Java favors the "all zero" bit pattern as normative.  Different CPUs
> may disagree on which bits denote signaling or quiet NaNs, and when
> such bits may be queried or modified.  Adding the possible distinct
> treatment of the "same" NaN value in compiled vs. interpreted code
> (as well as strictfp vs. non-strictfp code), and the use of "raw" NaN
> bits seems a very risky proposition, useful only for people writing
> processor-specific code, with great care.
> In hindsight, I think it would have been nice to place the "raw bits"
> API points to Unsafe or a separate module.  But when those API
> points were designed (1.0), there were no such hiding places.
> And it's probably too costly to fix now.  If the sweet spot is to
> acknowledge the wart, but not let it spread, then we design the
> substitutability test based on Float::equals, not floatToRawIntBits.
> — John
> On Jan 6, 2019, at 4:36 PM, Hans Boehm <hboehm at google.com> wrote:
> >
> > IIUC,  isSubstitutible() is not quite what's being proposed here. The
> > proposed definition here uses floatToIntBits(), not floatToRawIntBits().
> >
> > Hans
> >
> > On Sun, Jan 6, 2019 at 3:59 PM Brian Goetz <brian.goetz at oracle.com>
> wrote:
> >
> >> Followers of Project Valhalla will see that this issue comes up when
> >> defining equality on value types.  The relation you are looking for is
> >> being called "substitutible"; it asks whether there is any way to
> >> distinguish between two values.  For primitives other than float/double,
> >> this coincides with `==`, and similarly for references.
> >>
> >> An `isSubstitutible()` API point will likely emerge from Valhalla.

More information about the core-libs-dev mailing list