什么是perl中的MAX_INT等效值?

20

我是perl的新手,正在寻找一个@array中的最小值。是否有一些代表非常大整数的常量?

我知道我可以对数组进行排序并取开头,但这似乎浪费了很多CPU周期。在Perl中,有什么优雅的解决方案来解决我的问题?


最好进行排序。排序的时间复杂度为O(n log n)。与遍历(O(n))相比,只有当你有数千到数百万个项目的数组时才会成为问题。 - Niet the Dark Absol
我不喜欢那个答案。Perl是不是意味着要成为一种慢语言?当然不是。肯定有更优雅的解决方案。难道没有最大值吗?!? - Zak
Perl 内部使用 快速排序,因此我猜最坏情况仍然是 O(n log n) - Krishnachandra Sharma
快速排序的时间复杂度为O(n^2)。但是Perl不再使用快速排序。自5.8.0版本以来,它使用归并排序。 - ikegami
快速排序的数学分析表明,平均而言,该算法需要 O(n log {n}) 次比较来对 n 个项目进行排序。在最坏情况下,它需要 O(n^{2}) 次比较。 - Zak
6个回答

32

为了回答你实际提出的问题(尽管这对你并没有真正用处):

  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 我很惊讶地发现我的所有 Perl 都似乎没有 $Config{ivmax}$Config{uvmax}。在 blead Perl 源代码中搜索也没有找到任何信息。您能分享一下您是如何获取这些配置条目的吗? - amon
1
@amon,我写下这句话时可能正在睡觉。没有任何数乘以8可以得到MAX_INT(尽管$Config {ivsize} * 8可以给出位数)。已修复。 - ikegami
1
感谢您将问题标记为已回答,因为我们中的一些人在谷歌上快速搜索时仍然会找到这个问题,即使从原帖作者的角度来看,它实际上并不需要这个答案。+1 - Dereleased
1
请问可以存储的最小有符号(负数)整数是多少? - Ωmega
1
@Ωmega,作为有符号整数,-(~0 >> 1)-1 - ikegami

21
一般情况下,您可以使用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;

非常感谢你提供如此棒且详尽的回答!+1 - Zak
1
请注意,对于空数组(undef),所有三个返回值都相同! - ikegami
更简单的非库版本:my $min = $array [0]; 对于我的价值观@array { 如果$value < $min,则$min = $value; }(是的,它会进行一次额外的比较,但它会减少(N-1)和(N-1)*2个变量查找。但更重要的是,它是更简单的代码。) - ikegami

4

9**9**9 可以工作。在许多版本/平台的perl上,0+'inf' 也可以使用。


对我来说,两者都只返回“Inf”。(Perl v5.22.1在Linux 4.13.0-37-generic x86_64上) - mivk

2

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 表示浮点数值。

你应该使用适合你目的的工具,而不是模糊的 hack;如另一个答案中提到的 List::Util::min 就非常好。只是想让你确认一下你最初的问题 :)


1
是的,“N”代表数字。还有UV表示无符号整数。 - ikegami

0

1
这并不适用于所有Perl的编译版本。 - ikegami

-2

Perl 可以存储的最大整数值为 9,007,199,254,740,992。

我不知道是否有一个专门针对此的常量。


不!我把它存储在变量中,并不断递增,它有效! - Krishnachandra Sharma
这对于32位的Perl来说是半真的(2^53是您可以在标准双精度浮点数中存储的最小数字,因此x和x + 1不可区分),而对于64位的Perl来说则绝对是错误的。 - hobbs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接