Indeed.  During the early explorations for this feature we got fooled by values for which casting from T to U lost precision, but the corresponding cast back from U to T was also imprecise, and so the round-trip T -> U -> T preserved the input value.  We scratched our heads over this for a while.


On 11/16/2022 10:15 AM, Dan Heidinga wrote:
It's good to hear that you and others are thinking through the details on how float/doubles will work.

I still have some concern with user-intuition when writing pattern matching code over floating point values if users base their intuition on their experience with widening casts to float.  There's a great sample program (JLS Example 5.1.2-1) which shows the loss of precision when casting a large int to a float which I would try to express with pattern matching roughly as:

record FloatBox(float f) {}
int big = 1234567890;
FloatBox box = new FloatBox(big);
if (box instanceof FloatBox(int i)) {
   // pattern won't match here
}

I think users would be surprised reading the code that the pattern doesn't match because converting back to an int would lose precession.

The equivalent non-pattern code would be pretty clear that it accepted the loss of precession:

if (box instanceof FLoatBox) {
  int i = (int)box.f();
  ....
}

Users will find it confusing when the pattern seems to match "sometimes" though this is likely due to existing confusion related to floating types.  Maybe expanding on the expected implementation will make it easier to build a mental model for when the match will succeed?

--Dan


On Tue, Nov 15, 2022 at 6:13 PM Joseph D. Darcy <[email protected]> wrote:

    On 11/15/2022 12:13 PM, Brian Goetz wrote:
    >
    >
    > On 11/15/2022 2:55 PM, Dan Heidinga wrote:
    >> Hi Angelos,
    >>
    >> The overall direction and writeup for this looks good to me.  I
    think
    >> we need to be more specific about how doubles & floats fit into
    this
    >> though as they are perpetual source of special cases.
    >
    > Indeed, floating point is the gift that keeps on giving.
    >
    > Joe recently did some nice work in the spec of Float and Double,
    > outlining the various different ways in which floats can be
    compared.
    > This allows language features like pattern matching, casting, and
    > switch to appeal to "compared by FooBar comparison", rather than
    > spelling it out for each use.
    >
    >
    FYI, the new text in question is:

    
https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/Double.html#fpNumericalEq
    
<https://urldefense.com/v3/__https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/Double.html*fpNumericalEq__;Iw!!ACWV5N9M2RV99hQ!NLeYfZTwyKuJa79r6BKK7vCpK18EfV6UFYQATED31R-rgD9GThj4b5Apwa-MjRhTkfthC6sXdBLheOEVZLA$>

    For the cases in the draft JEP, there have been separate discussions
    working through the details. Putting aside how it might be
    implemented,
    for the

        floating-point type -> integral type

    cases, conceptually if the same real number can be presented in the
    floating-point type and the integral type, then the conversion is
    exact.
    (While floating-point values are often thought of as "fuzzy," each
    finite floating-point value represents some particular real number.
    Finite binary floating-point values are sums of the powers of 2 where
    the exponent difference of the powers is bounded by the significand
    width of the floating-point format in question.) The main special
    case
    is how conversion of -0.0 to an integral type is defined for
    purposes of
    instanceof. The desired double -> float behavior can be inferred from
    IEEE 754 concepts.

    HTH,

    -Joe

Reply via email to