【问题标题】:Is it possible to overcome this 32-bit limitation?是否有可能克服这个 32 位限制?
【发布时间】:2012-01-24 06:04:41
【问题描述】:

List::Gen 中的 cartesian 函数似乎受到我的 64 位 Windows 操作系统上无符号 32 位上限的限制:

use strict;
use warnings;
use List::Gen '*';
use 5.010;
use bigint;               # This didn't help either

say $List::Gen::VERSION;  # 0.80

my $diameters = range( 1, 175 );
my @five_in_a_row = ( $diameters ) x 5;

my $combinations = cartesian { \@_ } @five_in_a_row;

say 0+@$combinations;   # Should be 175**5 == 164_130_859_375
                        # prints -1+2**31  ==   2_147_483_647

有没有办法克服这个限制?我的 Perl 构建详细信息如下。

> perl -v

这是 perl 5, version 12, subversion 3 (v5.12.3) 为 MSWin32-x64-multi-thread(有 9 个注册补丁,参见 perl -V for 更详细)

【问题讨论】:

  • 操作系统“位数”无关紧要。看起来它是 Perl 的 64 位版本,所以应该使用 64 位整数。请确认perl -V:ivsize 是8。
  • @ikegami : ivsize='8';
  • 我在cartesian 中得到“不是数组引用”。它正在尝试对 @five_in_a_row 的内容进行数组解引用。
  • @ikegami :我使用的是旧版本的List::Gen (0.80)。为我工作。
  • @ikegami:你也可以试试my @five_in_a_row = ( [ @$diameters ] ) x 5;。或者完全忘记范围并使用( [ 1..175 ] ) x 5;。问题依然存在。

标签: perl 32bit-64bit


【解决方案1】:

由于 perl 将数组索引拟合为 32 位或 64 位整数,因此与生成器的绑定接口总是会受到限制。在这个范围之外,你可以使用面向对象的接口来生成生成器,它不仅限于2**31-1,而且比绑定接口快得多。

my $combinations = cartesian {\@_} map {range 1 => 175} 1 .. 5;

say $combinations->size; # 164130859375

并获取一个元素:

my $x = $combinations->get(164130859374);

my $x = $combinations->(164130859374);

我将在下一个版本之前将自动检测到的 64 位限制添加到改进列表中。

【讨论】:

    【解决方案2】:

    List::Gen 明确将结果限制为 2**31-1。

    sub FETCHSIZE {
        ...
        my $fetchsize = sub {
            my $size  = $realsize->();
            $size > 2**31-1
                  ? 2**31-1
                  : $size
        };
        ...
    }
    

    你可以改成

    use Config qw( );
    my $max_iv = $Config::Config{ivsize} == 8 ? 2**63-1 : 2**31-1;
    
    sub FETCHSIZE {
        ...
        my $fetchsize = sub {
            my $size  = $realsize->();
            $size > $max_iv
                  ? $max_iv
                  : $size
        };
        ...
    }
    

    【讨论】:

    • 很奇怪。我的代码现在返回 922_102_127,比以前更小:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    相关资源
    最近更新 更多