perlのvec関数で扱えるビット列の最大長は当たり前だけど2147483647ビット

プログラミングっていうのはサッカーやピアノなどの習い事と同じで、サボっているとすぐに感覚が鈍ってうまくできないような気がします。 そんな訳で Project Eulerの問題を解くことを習慣にしようとしています(まだ習慣にはなっていない)。
ここで出される問題では時として100万を越えるような大きな数を扱います。 例えば100万未満の素数をすべて求めるみたいなことがあります。 その時に100万個の要素を持つ配列を用意するのは非現実的すぎるので、100万桁のビット列を用意してNが素数だったらNビット目のビットを立てるということをします。ここで使えるのが長〜いビット列を扱えるperlのvec関数です。

$bits = '';
vec($bits,4,1) = 1; #"00001000"

if(vec($bits,4,1)){print "true";} #true

こんな感じで使います。一つ目の引数にビット列を格納する変数、2つ目の引数にインデックス、3つ目は扱うビット幅が入ります。 で、先日使っていたところ下記のようなエラーが出て来ました。

Negative offset to vec in lvalue context at -e line 1.

2つ目のインデックスに負の値が指定されているよ!って怒られました。負の値なんて指定していなかったのに・・。 これはおそらくvecで扱えるビット列の最大長を超えたインデクスのビットを立てようとしたから。 なのでvecで扱えるビット列の最大長を調べてみたました。

$ perl -e '$i=2147399706;while(1){print "$i\n";vec($vec,$i,1)=1;$i++;}' 
(省略)
2147483639
2147483640
2147483641
2147483642
2147483643
2147483644
2147483645
2147483646
2147483647
2147483648
Negative offset to vec in lvalue context at -e line 1.

どうやら2147483647が最大長のようです。ってこれintの最大値ですね。常識的に考えてそうだわな。多倍長とか期待した僕が間違っていたようです。あ、でも簡単に実装できるような気がします。今日はここまで〜。