Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re^2: Largest integer in 64-bit perl

by ikegami (Patriarch)
on May 27, 2025 at 12:17 UTC ( [id://11165136]=note: print w/replies, xml ) Need Help??


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

What a weird lesson to take. You'll have "problems near 2**53" in those languages too! Only by using a 64-bit int can you go further. The difference is that Perl does this automatically! Perl is actually better at this.

Replies are listed 'Best First'.
Re^3: Largest integer in 64-bit perl
by LanX (Saint) on May 27, 2025 at 12:36 UTC
    > The difference is that Perl does this automatically!

    Is a whole number at the extreme of a mantissa's precision really converted to 64 bit integer if incremented?

    My results from binary search indicated otherwise. This might also depend on the type of operation.

    Plus might do, mult might stick with float.

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

      [Upd: This pertains to when using addition.] An int, yes. A float, no. Just like in C. Ints are promoted to floats, but floats aren't promoted to integers. You need to cast to int to get int behaviour. Just like in C.

      use v5.14; use warnings; my $x = 2**53; say sprintf "%d", $x; say sprintf "%d", $x + 1; say sprintf "%d", int( $x ) + 1;
      #include <inttypes.h> #include <stdint.h> #include <stdio.h> int main( void ) { double x = 9007199254740992; printf( "%"PRIu64"\n", (uint64_t)( x ) ); printf( "%"PRIu64"\n", (uint64_t)( x + 1 ) ); printf( "%"PRIu64"\n", (uint64_t)( (uint64_t)x + 1 ) ); }
      9007199254740992 9007199254740992 9007199254740993

      Other differences between floats and ints is the existence of inifinity, NaN and -0.

        .... but floats aren't promoted to integers.

        It can get a bit moot:
        D:\>perl -MDevel::Peek -le "$x = (2 ** 53) - 1; Dump $x; $x++; Dump $x +; $x++; Dump $x; $x++; Dump $x;" SV = NV(0x28e88c5a2f8) at 0x28e88c5a310 REFCNT = 1 FLAGS = (NOK,pNOK) NV = 9007199254740991 SV = PVNV(0x28e88c24e10) at 0x28e88c5a310 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 9007199254740992 NV = 9007199254740991 PV = 0 SV = PVNV(0x28e88c24e10) at 0x28e88c5a310 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 9007199254740993 NV = 9007199254740991 PV = 0 SV = PVNV(0x28e88c24e10) at 0x28e88c5a310 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 9007199254740994 NV = 9007199254740991 PV = 0
        The fact that the flags change from (NOK,pNOK) to (IOK,pIOK) suggests to me that the NV has been promoted to an IV.
        Or does the fact that both the IV and NV slots have been filled suggest that it's neither an IV nor an NV. Or maybe that suggests that it's both ? ... I don't know.

        Anyway, I'm not looking for an argument. It's just one of those things that I find a little mysterious.

        Other differences between floats and ints is the existence of inifinity, NaN and -0

        One of my beefs with Math::BigInt is that it has a NaN and an inf:
        D:\>perl -MMath::BigInt -le "$x = Math::BigInt->new(2.3); print $x; pr +int ref($x);" NaN Math::BigInt D:\>perl -MMath::BigInt -le "$x = Math::BigInt->new(1) / 0; print $x; +print ref($x);" inf Math::BigInt
        I don't regard it as all that important, but it probably shouldn't do that.
        I couldn't quickly get it to provide a "-0", but I did get the following weirdness:
        D:\>perl -MMath::BigInt -le "$x = Math::BigInt->new(1) / inf; print $x +; print ref($x);" 0 Math::BigInt D:\>perl -MMath::BigInt -le "$x = Math::BigInt->new(1) / -inf; print $ +x; print ref($x);" -1 Math::BigInt
        Cheers,
        Rob
Re^3: Largest integer in 64-bit perl
by karlgoethebier (Abbot) on May 29, 2025 at 09:52 UTC

    ”…weird lesson to take. You'll have "problems near 2**53" in those languages too!”

    I'm not so sure about that. Or at least I don't see the problems:

    use anyhow::{Context, Result}; use num::BigUint; fn frob(n: u64) -> Result<BigUint> { Ok((1..=n) .into_iter() .map(|i| BigUint::from(i)) .reduce(|a, b| a * b) .context("fuba")?) } fn main() -> Result<()> { println!("i8 {}", i8::MAX); println!("i16 {}", i16::MAX); println!("i32 {}", i32::MAX); println!("i64 {}", i64::MAX); println!("i128 {}", i128::MAX); println!("u8 {}", u8::MAX); println!("u16 {}", u16::MAX); println!("u32 {}", u32::MAX); println!("u64 {}", u64::MAX); println!("u128 {}", u128::MAX); println!("f32 {}", f32::MAX); println!("f64 {}", f64::MAX); println!("{}", frob(1000)?); Ok(()) }

    In any case, this seems to be a clearly defined matter in this case.

      The discussion in this thread is about the side effects of implicit typecasting/conversions of whole numbers to augment precision when operations may cause an overflow.

      Perl does this by switching to double floats with E0 were the mantissa has 53 bits (opposed to integers with 32 or 64 bits, depending on the built).

      Now from what I read on Wikipedia is Rust strictly typed.

      Hence I really don't understand what your code is supposed to show.

      Is there any implicit typecasting in your code?°

      update

      According to this tutorial: https://oylenshpeegul.gitlab.io/from-perl-to-rust/numbers.html this can't be, because coercion has to be made explicitly.

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

        Perl does this by switching to double floats ...

        Rather, perl switches to "NV" floats.
        Of course, I'm nitpicking, but it's a nitpick that does have some significance.
        On a perl whose ivsize=8, && whose nvtype is either 'long double' or '__float 128', I get:
        D:\>perl -e "print 'wtf' unless ~0 < (~0) + 1;" D:\>
        But on a perl where ivsize=8 and nvtype is 'double' and you get:
        D:\>perl -e "print 'wtf' unless ~0 < (~0) + 1;" wtf D:\>
        Now that particular configuration (ivsize==8 and nvtype is 'double') is the only perl configuration that produces that nonsense - and yet it's the most commonly used configuration !!
        If you use either an ivsize of 4, or an nvtype that is not double, then you can ignore that particular weirdness because it's not going to happen.

        Note: That "nonsense" doesn't just happen with (~0) + 1. It happens for (~0) + $x for all $x in the range 1..2048.
        That's mainly why I think of it as an insane configuration. (It's still a configuration that I regularly use ;-)

        Cheers,
        Rob

      I don't see any incrementing beyond 2**53 (or any incrementing at all) in there. I don't know what you're trying to prove, but it doesn't relate to the passage you quoted.

      That's Raku/Perl6?

      (at least I'm not aware of any other language applying use to import a module)

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

        ”…any other language applying use…”

        There are some more:

        with Alien; with Utils; use Utils; package Superiour is type Acme is new Alien.Object with null record; function Shred (Self : Object) return String; end Superiour;
Re^3: Largest integer in 64-bit perl
by BillKSmith (Monsignor) on May 31, 2025 at 21:21 UTC
    When I referred to "Application which require integers ...", I assumed that the reason that they required integers was that they needed mathematically exact results. Yes, the typed languages usually require you to explicitly specify an appropriate integer type. I still believe that my conclusion holds in this case.
    Bill
      I'm no expert in statically typed languages..

      ... how many of them support x^y with integers?

      Those exponentiation algorithms are normally implemented for real numbers and produce a float.

      The core problem we saw and most Perl experiments here is that 2**53 is a float whose error margin doesn't allow a consistent conversion to 64 bit integer anymore.

      If your statically typed language doesn't support this out-of-the-box - and Perl is build on top of C - your statement is just comparing apples with oranges.

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

        I would expect any language that does not support an operation to not allow attempts to use it. Perl does not directly support 64-bit integer exponentiation. without strong typing, it has no way to know that we expect it. What it does do when we try to raise an integer to an integer power is exact if the result is less than 2**53, and almost always 'good enough" the rest of the time. 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.
        Bill

      You'll have the same problems using doubles near 2**53 in another language. You'd have to use 64-bit ints to avoid that. Same in Perl. It doesn't hold.

        Here is a few examples of the same expression in strawberry perl 5.38.2 and in the gfortran packaged with it. I believe the fortran.
        use strict; use warnings; use integer; use feature 'say'; my $base = 3; my $power = 33; my $result = $base ** $power; printf "%d\n", $result; $power = 38; $result = $base ** $power; printf "%d\n", $result
        program fort integer*8 base, power integer*8 result base = 3 power = 33 result = base ** power +1; print *, result power = 38 result = base ** power +1; print *, result end program

        RESULTS

        C:\Users\Bill\forums\monks>perl power3.pl 5559060566555523 1350851717672992000 C:\Users\Bill\forums\monks>gfortran -o power3 power3.f90 C:\Users\Bill\forums\monks>power3.exe 5559060566555524 1350851717672992090
        Bill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2025-07-14 01:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.