20

I am new to perl and seeking the lowest value in an @array. Is there some constant that represents a very large integer number?

I know I could sort the array and take the beginning, but that seems to be a lot of wasted CPU cycles. What is an elegant solution to my problem in Perl?

Zak
  • 12,213
  • 21
  • 59
  • 105
  • It's probably best to sort. Sorting is `O(n log n)`. When compared to traversing (`O(n)`) it's only a problem if you have arrays with thousands to millions of items. – Niet the Dark Absol Feb 28 '13 at 05:16
  • I don't like that answer. Is Perl meant to be a SLOW language? Surely not. There must be a more elegant solution. Is there no MAX value?!? – Zak Feb 28 '13 at 05:22
  • Perl internally uses *Quick Sort*, hence I guess worst case will still be `O(n log n)`. – Krishnachandra Sharma Feb 28 '13 at 05:35
  • Quick Sort is O(n^2). But Perl doesn't use Quick Sort anymore. Since 5.8.0, it uses Merge Sort. – ikegami Nov 29 '22 at 22:46
  • Mathematical analysis of quicksort shows that, on average, the algorithm takes `O(n log {n})` comparisons to sort `n` items. In the worst case, it makes `O(n^{2})` comparisons. – Zak Dec 01 '22 at 21:25

6 Answers6

31

To answer you the question you actually asked (even though it's not really of use to you):

  1. Largest integer value that can be stored as a signed integer.

    say ~0 >> 1;
    
  2. Largest integer value that can be stored as an unsigned integer.

    say ~0;
    
  3. All integer values from 0 to this number can be stored without loss as a floating point number.

    use Config qw( %Config );
    say eval($Config{nv_overflows_integers_at});
    

    Note that some larger integers can be stored without loss in a floating point number, but not the one 1 higher than this.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • @ikegami I was surprised to find that none of my perls seem to have `$Config{ivmax}` or `$Config{uvmax}`. Grepping through the blead Perl source didn't reveal anything either. Could you share how you obtained these config entries? – amon Apr 26 '14 at 08:24
  • 1
    @amon, I must have been asleep when I wrote that. There is nothing multiplied by 8 that gives MAX_INT (though `$Config{ivsize}*8` gives the number of bits). Fixed. – ikegami Apr 26 '14 at 22:05
  • 1
    Thanks for answering the question as answered, since those of us searching for a quick hit on google still land on this question, even if it didn't actually need this answer from the OP's perspective. +1 – Dereleased Sep 24 '15 at 16:17
  • 1
    And what would be the smallest signed (negative) integer that can be stored, please? – Ωmega Sep 20 '18 at 20:55
  • 1
    @Ωmega, As a signed int, `-(~0 >> 1)-1` – ikegami Sep 20 '18 at 21:20
21

In the general case, you can use undef to signal a non-existent value; perl scalars aren't restricted to holding just integers. That would be written:

my $min; # undef by default
for my $value (@array) {
  $min = $value if !defined $min or $value < $min;
}

But there are some simpler options here. For example, initialize $min to the first value in the array, then compare to the rest:

my $min = $array[0];
for my $i (1 .. $#array) {
  $min = $array[$i] if $array[$i] < $min;
}

Or just use a built-in function:

use List::Util 'min';
my $min = min @array;
hobbs
  • 223,387
  • 19
  • 210
  • 288
  • Thank you for the very awesome and thorough answer! +1 – Zak Feb 28 '13 at 05:55
  • 1
    Note that all three return the same result for an empty array (`undef`)! – ikegami Feb 28 '13 at 11:03
  • Simpler non-library version: `my $min = $array[0]; for my $value (@array) { $min = $value if $value < $min; }` (Yes, it does one extra comparison, but it does between (N-1) and (N-1)*2 fewer var lookups. But more importantly, it's simpler code.) – ikegami Jun 29 '17 at 16:07
4

9**9**9 works. So does 0+'inf' on many versions/platforms of perl.

ysth
  • 96,171
  • 6
  • 121
  • 214
2

Perl isn't C; if you try to compute an integer that's too large, you get a floating-point result instead (unless you use bigint, which makes integers unbounded). Beyond that, you get inf.

You can see this with Devel::Peek, which shows you Perl's internal representation of a value:

$ perl -E 'use Devel::Peek; Dump(1000); Dump(1000**100); Dump(1000**100 + 1)'
SV = IV(0xcdf290) at 0xcdf2a0
  REFCNT = 1
  FLAGS = (PADTMP,IOK,READONLY,pIOK)
  IV = 1000
SV = NV(0xd04f20) at 0xcdf258
  REFCNT = 1
  FLAGS = (PADTMP,NOK,READONLY,pNOK)
  NV = 1e+300
SV = NV(0xd04f18) at 0xcdf228
  REFCNT = 1
  FLAGS = (PADTMP,NOK,READONLY,pNOK)
  NV = 1e+300

IV indicates an integer value; NV indicates a floating-point (Number?) value.

You should definitely use a tool suited to your purpose instead of a fuzzy hack; List::Util::min as mentioned in another answer is excellent. Just thought you might like confirmation on your original question :)

Eevee
  • 47,412
  • 11
  • 95
  • 127
0

Here :http://www.perlmonks.org/?node_id=718414

I got an answer that I could verify on linux 64

18,446,744,073,709,551,615 = (2 ^64)-1

terary
  • 940
  • 13
  • 30
-2

The biggest integer value perl can store is 9,007,199,254,740,992

I don't know if there's a constant specifically for that.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • No! I stored this in variable, and kept on incrementing, and it works! – Krishnachandra Sharma Feb 28 '13 at 05:28
  • This is semi-true for 32-bit perl (2^53 is the smallest number you can store in a standard double-precision float so that x and x+1 aren't distinguishable) and definitely false for 64-bit perl. – hobbs Feb 28 '13 at 05:50