Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Non-integer print output???

by syphilis (Archbishop)
on Sep 10, 2021 at 00:53 UTC ( [id://11136623]=note: print w/replies, xml ) Need Help??


in reply to Non-integer print output???

So why does perl convert a number that will obviously fit inside a 64 bit integer to floating point?

Firstly, note that the ** operator always returns an NV:
C:\>perl -MDevel::Peek -le "$x = 2 ** 3; Dump $x;" SV = NV(0x47cd88) at 0x47cda0 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 8 C:\>perl -MDevel::Peek -le "$x = 2 ** 49; Dump $x;" SV = NV(0x33d148) at 0x33d160 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 562949953421312 C:\>perl -MDevel::Peek -le "$x = 2 ** 50; Dump $x;" SV = NV(0x47cd38) at 0x47cd50 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 1.12589990684262e+15
(Maybe the question you should ask is "Why does the ** operator always return an NV ?". I don't know.)

What you've displayed is that perl sometimes decides that an NV will be printed (interpolated) as an integer, and sometimes printed as a float.
Obviously, non-integer NVs will always be printed as floats - no problems there.

Now, perl still adheres to the utterly fuckbrained notion that, when nvtype is double, print() will never present more than 15 significant digits.
And that's what you're seeing here.
The NV returned by the operation 2 ** 50 contains 16 significant digits which, by this idiotic rule, must be interpolated to 15 digits. And that's what perl duly does.
But if the NV contains an integer value comprising less than 16 significant digits that is in the range IV_MIN to UV_MAX (eg 2 ** 50 2 ** 49), then it will be interpolated as an integer.

On a perl whose nvtype is long double fully quad IEEE 754 long double or __float128, you should find this particular anomaly to be absent - because the 15-digit limit does not apply there.
Thre's still an absurdly low limit, but it's large enough to prevent this particular case presented here.

Cheers,
Rob

Replies are listed 'Best First'.
Re^2: Non-integer print output???
by LanX (Saint) on Sep 10, 2021 at 09:12 UTC
    > (Maybe the question you should ask is "Why does the ** operator always return an NV ?". I don't know.)

    The exponentiation operator a**b is IIRC optimized to generally handle float input for a and b and is approximating the result.

    The result is hence usually a float.

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

      The exponentiation operator a**b is IIRC optimized to generally handle float input for a and b and is approximating the result.

      Does this arise because C's pow/powl/powq functions take floating point inputs and return floating point values ?
      I've always assumed so, without ever really knowing.

      I'm a little surprised that the C language doesn't provide a pow() function that takes and returns signed long int (or signed long long int) values - though I guess such a function would easily overflow for relatively low input values.

      Cheers,
      Rob
        As I said, it's AFAIR an approximation algorithm.

        I quickly found efficient integer algorithms too, can't tell why they are not included.

        I suppose it's provided by the CPU/ MMU?

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

Re^2: Non-integer print output???
by jwkrahn (Abbot) on Sep 10, 2021 at 01:19 UTC

    Thanks for the info.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11136623]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (None)
    As of 2024-04-19 00:04 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found