in reply to Re^2: Introspection into floats/NV
in thread Introspection into floats/NV

I “discussed” your one liner and ikegamis sub and asked a question on pack/unpack similar to yours. Also impressive: A version of ikegamis sub with POD. The oracle liked the sub. A while ago i asked something about FFI::Platypus with Rust - which can be very tricky. The oracle provided a solution that i never would have found in the (good) docs.

Replies are listed 'Best First'.
Re^4: Introspection into floats/NV
by LanX (Saint) on Jun 04, 2025 at 15:52 UTC
    > I “discussed” your one liner and ikegamis sub

    By feeding our old code you gave it a reasonable headstart.

    It would have been interesting to know the solution without that.

    After googling I also found an old similar solution of our one and only ikegami at SO

    https://stackoverflow.com/questions/7669010/binary-representation-of-float-to-decimal-conversions-in-perl

    Most of my problems came from understanding the effect of little endian on the pack, till I discovered the ">" modifier.

    How can the AI know what hardware I'm using?

    It's would also be interesting to have more insights in the difference of "d" and "F" templates. I'm expecting the latter to be more portable.

    Supporting other NV formats from the compile options would be nice too.

    Note how I used B* not B64 in the unpack.

    Unfortunately I don't have other builds and hardware to test.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

      See Mini-Tutorial: Formats for Packing and Unpacking Numbers

      F is for the build's NV
      d is for the build's double

      The sub requires an IEEE double.

      There's no way to know if F is an IEEE double or not.
      There's no way to know if d is an IEEE double or not.

      But as far as I know, double and thus d is an IEEE double on all machines on which Perl currently runs.

      But some people build Perl which uses long double for NV. So d is more reliable for a sub requiring an IEEE double.

      But since you're more interested in inspecting an NV, F would make more sense for you. But you would also need to handle formats other than an IEEE double.

        > There's no way to know if F is an IEEE double or not.

        I'm confused, I'm expecting F to return 32, 64, 80 or 128 bits (at least)

        And d always 64 bits

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery

      Update: Caveat Lector: The table below Perl `pack` Template Comparison: "d" vs "F" was generated by ChatGPT and is wrong. For explanation see Re^10: Introspection into floats/NV and Re^12: Introspection into floats/NV as well as Re^11: Introspection into floats/NV.

      ”How can the AI know what hardware I'm using?”

      Magic or voodoo? I don’t know.

      ”…have more insights in the difference of "d" and "F" templates.”

      Probably this isn’t new to you:

      Perl `pack` Template Comparison: "d" vs "F" =========================================== Summary Table ------------- | Template | Type | Precision | Bits | Description + | |----------|--------|--------------|------|--------------------------- +---------| | "d" | double | 64-bit float | 64 | IEEE 754 double-precision +float | | "F" | float | 32-bit float | 32 | IEEE 754 single-precision +float | Example Code ------------ use feature 'say'; my $x = 1/3; say "Double:"; say unpack("B64", pack("d>", $x)); # Big-endian double say "Float:"; say unpack("B32", pack("F>", $x)); # Big-endian float Difference Illustration ----------------------- my $x = 1/3; my $float_bin = unpack "B32", pack "F>", $x; my $double_bin = unpack "B64", pack "d>", $x; printf " Float (32-bit): %s\n", $float_bin; printf "Double (64-bit): %s\n", $double_bin; Expected Output: Float (32-bit): 00111110101010101010101010101011 Double (64-bit): 0011111111010101010101010101010101010101010101010101 +010101010101 IEEE 754 Format Summary ----------------------- | Precision | Sign | Exponent | Mantissa (Significand) | Bias | |-----------|------|----------|-------------------------|------| | Float | 1 bit | 8 bits | 23 bits | 127 | | Double | 1 bit | 11 bits | 52 bits | 1023 | Usage Notes ----------- - Use "d" / "d>" if you want: - Higher precision - Full 64-bit IEEE 754 compliance - Direct compatibility with most CPUs' `double` type - Use "F" / "F>" if you want: - Reduced memory size - Exact compatibility with 32-bit float structures (e.g., in network + protocols or embedded devices) Endianness Reminder ------------------- - d> and F> -> big-endian - d< and F< -> little-endian - d and F (no angle) -> native-endian (machine dependent)

        That's completely wrong [Update: except the bit on endianness].

        • d isn't defined as an IEEE 754 double-precision float. (That said, it virtually always is.)
        • F isn't defined as a float, and it's unlikely to be one.
        • F isn't defined as an IEEE 754 single-precision float, and it's unlikely to be one.
        • An IEEE 754 single-precision float doesn't have 32 bits of precision.
        • An IEEE 754 double-precision float doesn't have 64 bits of precision.
        • F is probably the same d or something larger, not something smaller.

        See Mini-Tutorial: Formats for Packing and Unpacking Numbers.

        d is a double
        It is likely to be an IEEE 754 double-precision float, but it might not be.

        f is a float
        It is likely to be an IEEE 754 single-precision float, but it might not be.

        F is an NV
        It is likely to be an IEEE 754 double-precision float.
        It is possibly an IEEE 754 quad-precision float.
        It's unlikely to be an IEEE 754 single-precision float.
        It's conceivable for it to be an Intel 80-bit extended precision float.
        It might be none of those.

        An IEEE 754 quad-precision float will be 128 bits in size and have 133 bits of precision (or less for subnormals).
        An IEEE 754 double-precision float will be 64 bits in size and have 53 bits of precision (or less for subnormals).
        An IEEE 754 single-precision float will be 32 bits in size and have 24 bits of precision (or less for subnormals).
        An Intel 80-bit extended precision float will be at least 80 bits in size and have 64 bits of precision (or less for subnormals).