Каков Perl-эквивалент MAX_INT?

Я новичок в perl и ищу наименьшее значение в @array. Существует ли какая-то константа, представляющая очень большое целое число?

Я знаю, что мог бы отсортировать массив и взять начало, но это, похоже, много потраченных впустую циклов процессора. Каково элегантное решение моей проблемы в Perl?


person Zak    schedule 28.02.2013    source источник
comment
Наверное, лучше отсортировать. Сортировка O(n log n). По сравнению с обходом (O(n)) это проблема, только если у вас есть массивы с тысячами и миллионами элементов.   -  person Niet the Dark Absol    schedule 28.02.2013
comment
Мне не нравится этот ответ. Perl должен быть МЕДЛЕННЫМ языком? Конечно нет. Должно быть более элегантное решение. МАКСИМАЛЬНОГО значения нет?!?   -  person Zak    schedule 28.02.2013
comment
Perl внутри использует Quick Sort, поэтому я предполагаю, что в худшем случае все равно будет O(n log n).   -  person Krishnachandra Sharma    schedule 28.02.2013


Ответы (6)


В общем случае вы можете использовать undef для обозначения несуществующего значения; Скаляры perl не ограничиваются хранением только целых чисел. Было бы написано:

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

Но есть и более простые варианты. Например, инициализируйте $min первым значением в массиве, а затем сравните с остальными:

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

Или просто используйте встроенную функцию:

use List::Util 'min';
my $min = min @array;
person hobbs    schedule 28.02.2013
comment
Спасибо за очень классный и исчерпывающий ответ! +1 - person Zak; 28.02.2013
comment
Обратите внимание, что все три возвращают один и тот же результат для пустого массива (undef)! - person ikegami; 28.02.2013
comment
Более простая небиблиотечная версия: my $min = $array[0]; for my $value (@array) { $min = $value if $value < $min; } (Да, она выполняет одно дополнительное сравнение, но между (N-1) и (N-1)*2 меньше поисковых запросов var. Но что более важно, это более простой код.) - person ikegami; 29.06.2017

Чтобы ответить вам на вопрос, который вы на самом деле задали (хотя это на самом деле вам не нужно):

  1. Наибольшее целочисленное значение, которое может быть сохранено как целое число со знаком.

    say ~0 >> 1;
    
  2. Наибольшее целочисленное значение, которое может быть сохранено как целое число без знака.

    say ~0;
    
  3. Все целые значения от 0 до этого числа могут быть сохранены без потерь как число с плавающей запятой.

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

    Обратите внимание, что некоторые большие целые числа могут быть сохранены без потерь в числе с плавающей запятой, но не в том, что на 1 больше, чем это.

person ikegami    schedule 28.02.2013
comment
@ikegami Я был удивлен, обнаружив, что ни у одного из моих перлов нет $Config{ivmax} или $Config{uvmax}. Просмотр исходного кода belead на Perl также ничего не выявил. Не могли бы вы поделиться, как вы получили эти записи конфигурации? - person amon; 26.04.2014
comment
@amon, я, должно быть, спал, когда писал это. Нет ничего, что умножается на 8, что дает MAX_INT (хотя $Config{ivsize}*8 дает количество битов). Исправлено. - person ikegami; 27.04.2014
comment
Спасибо за ответ на вопрос в том виде, в котором он был дан, поскольку те из нас, кто ищет быстрый ответ в Google, по-прежнему получают этот вопрос, даже если на самом деле этот ответ не нужен с точки зрения ОП. +1 - person Dereleased; 24.09.2015
comment
И каким будет наименьшее целое число со знаком (отрицательное), которое можно сохранить, пожалуйста? - person Ωmega; 20.09.2018
comment
@Ωmega, как целое число со знаком, -(~0 >> 1)-1 - person ikegami; 21.09.2018

9**9**9 работает. То же самое делает 0+'inf' на многих версиях/платформах perl.

person ysth    schedule 28.02.2013
comment
Для меня оба просто возвращают Inf. (Perl v5.22.1 в Linux 4.13.0-37-универсальный x86_64) - person mivk; 01.04.2018

Perl — это не C; если вы попытаетесь вычислить слишком большое целое число, вместо этого вы получите результат с плавающей запятой (если вы не используете use bigint, что делает целые числа неограниченными). Кроме того, вы получаете inf.

Вы можете увидеть это с помощью Devel::Peek, который показывает вам внутреннее представление значения в Perl:

$ 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 указывает целочисленное значение; NV указывает значение с плавающей запятой (Число?).

Вам определенно следует использовать инструмент, подходящий для вашей цели, а не нечеткий хак; List::Util::min как уже упоминалось в другом ответе, отлично. Просто подумал, что вам может понравиться подтверждение вашего первоначального вопроса :)

person Eevee    schedule 28.02.2013
comment
да, N означает число. Также есть UV для целых чисел без знака. - person ikegami; 28.02.2013

Здесь: http://www.perlmonks.org/?node_id=718414

Я получил ответ, который я мог проверить на Linux 64.

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

person terary    schedule 25.11.2014
comment
Этого не будет для всех сборок Perl. - person ikegami; 07.09.2016

Наибольшее целочисленное значение, которое может хранить perl, равно 9 007 199 254 740 992.

Я не знаю, есть ли константа специально для этого.

person Niet the Dark Absol    schedule 28.02.2013
comment
Нет! Я сохранил это в переменной и продолжал увеличивать, и это работает! - person Krishnachandra Sharma; 28.02.2013
comment
Это частично верно для 32-битного perl (2^53 — это наименьшее число, которое вы можете хранить в стандартном вещественном числе двойной точности, так что x и x+1 неразличимы) и определенно неверно для 64-битного perl. - person hobbs; 28.02.2013