in reply to Re^5: Weird behavior of int()
in thread Weird behavior of int()

I feel like 'int' ought to have a stronger contract of doing what's written on the label.

The documentation for int() says that it "Returns the integer portion of EXPR".
It's using "integer" in the mathematical sense of "whole number", not in the programming sense of "IV".
It just so happens that with the most commonly used builds of perl (where IV precision >= NV precision) every EXPR that (in numeric context) contains a fractional portion will also truncate to a value that fits into an IV ... so I can see how the confusion might arise.
But, for example, we don't want int(2 ** 65) to start returning '0' or 'undef' or IV_MAX just because it's too big to fit into an IV.

If you switch to a perl where IV precision < NV precision (such as perls whose IV size is 4 bytes, or whose NV type is __float128), then you'll encounter lots of cases where EXPR contains values with a fractional portion, and yet has an integer portion that's too big to fit into an IV.
On those builds, and for those values of EXPR, int(EXPR) will happily and silently return just the "whole number" portion of EXPR as an NV.

Cheers,
Rob

Replies are listed 'Best First'.
Re^7: Weird behavior of int()
by NERDVANA (Priest) on May 22, 2024 at 05:14 UTC
    I guess the unspoken implied behavior of a function named "int()" can be interpreted more ways than I expected. When I use "int()" in perl, what I actually wanted was C's cast-to-int or JavaScript's parseInt(), followed by making assumptions that I have an integer safe for any integer purposes.

    Having learned about these edge cases, now I need to go back through all the controllers I've written and fix:

    my $count= int($c->request->params->{count}); $c->detach(HTTP => 422, ["Invalid count"]) if $count < 0 || $count > $limit;
    because passing NaN to the controller would let a non-integer value leak through to the code beyond.
      When I use "int()" in perl, what I actually wanted was C's cast-to-int or JavaScript's parseInt()

      I don't know of any perl function that will do that.
      I'd do it as an XSub:
      SV * _to_IV(SV * in) { if(SvNV(in) < 0) return newSViv(SvIV(in)); return newSVuv(SvUV(in)); }
      However, in your case, assuming that $limit > ~0 >> 1, you could just do it as:
      IV _to_IV(SV * in) { return SvIV(in); }
      which (if I'm thinking correctly) would still reject arguments greater than ~0 >> 1 because $count is negative.

      Of course, you might prefer to just check that the arg is not a NaN, if you trust the NaN != NaN test or POSIX::isnan or somesuch.

      Cheers,
      Rob