in reply to Re^5: Largest integer in 64-bit perl
in thread Largest integer in 64-bit perl

> without strong typing, it has no way to know that we expect it.

I disagree, at least if the operands were integer and the result is between max-float-precision and max-integer-precision (2**53 and 2**64 in our case) you can assume an integer was wanted.

Of course it's not trivial (if ever) to solve this generally for instance for $x=2**0.5 and $y=$x**2 since the square-root of 2 isn't rational.

Or even $x=2/3 and 27**$x == 9 because $x isn't loss-free in binary floats.

> Perhaps there should be an optional warning when it attempts to cast a result greater than 2**53 and less than 2**63 to an integer.

I think this should be part of a (bigger) pragma to address this.

for instance will Perl happily do this

DB<25> p 27**(2/3) 9 DB<26> p 27**(2/3) == 9 DB<27> printf "%.15f", 27**(2/3) 8.999999999999998 DB<28>

update

And before the Perl bashing hits in, Python isn't that much better

>>> 27**(2/3) 8.999999999999998 >>> 27**(2/3)==9 False >>>

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

Replies are listed 'Best First'.
Re^7: Largest integer in 64-bit perl (RFC)
by LanX (Saint) on Jun 02, 2025 at 21:18 UTC
    > I disagree, at least if the operands were integer and the result is between max-float-precision and max-integer-precision (2**53 and 2**64 in our case) you can assume an integer was wanted.

    Here a POV to force ** into producing an integer where it obviously should.

    Kind of over-engineered and under-tested.

    I first used Math::BigInt as backend but integer turned out to be easier.

    Since integer is core, it shouldn't be complicated to implement this right away,

    use v5.10; use warnings; use Config; use constant { MAX_FLOAT => eval($Config{nv_overflows_integers_at}."-1"), MAX_INT => ~0, BACKEND => "integer", }; sub power{ my ($base,$exp) = @_; my $float = $base ** $exp; return $float + 0 # Explicitely coerce to IV if possible if $float <= MAX_FLOAT; return $float # no integer possible if $float > MAX_INT or $base != int($base) or $exp != int($exp); if (BACKEND eq "BigInt") { use Math::BigInt; my $result = Math::BigInt->new($base)->bpow($exp); return hex($result->as_hex()) } elsif (BACKEND eq "integer") { use integer; return int($base ** $exp); } else { die "Unknown Backend: ". BACKEND; } } sub compare { my ($b,$e) = @_; say "=== comparing $b^$e"; my $old = $b**$e; my $new = power($b,$e); for my $val ($old,$new) { say "--- $val"; # use Devel::Peek; # use Data::Dump; # say "is integer" if $val == int($val); # ddx ($val); # Dump($val); say "$_: \t", $val+$_ for -1,1; } say "="; } compare(@$_) for [2,50],[2,63];

    perl /home/lanx/perl/pm/int_pow.pl === comparing 2^50 --- 1.12589990684262e+15 is integer -1: 1125899906842623 1: 1125899906842625 --- 1125899906842624 is integer -1: 1125899906842623 1: 1125899906842625 = === comparing 2^63 --- 9.22337203685478e+18 is integer -1: 9.22337203685478e+18 1: 9.22337203685478e+18 --- 9223372036854775808 is integer -1: 9223372036854775807 1: 9223372036854775809 =

    update

    since integer is only meant to operate with signed integers I'm not too confident this is reliable in the range between 2**63 and 2**64.

    More testing needed.

    update

    well, seems not to be a good idea to rely on integer , see integer pragma buggy? (ANSWERED)

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