in reply to Largest integer in 64-bit perl

I found this thread to be very interesting. It motivated me to read most of the references. My conclusion is that any application which needs integers even close to 2**53 probably should not be written in native Perl. Even if you can make it work, future changes are likely to introduce subtle bugs. Use either the pragma bigint or the module Math::BigInt. If execution time is a problem, consider using a language with typed variables such as 'C' or 'FORTRAN'.
Bill

Replies are listed 'Best First'.
Re^2: Largest integer in 64-bit perl
by ikegami (Patriarch) on May 27, 2025 at 12:17 UTC

    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.

      > 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.

      ”…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

        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

      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

        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.