Integerの長さを超える配列を扱いたい


peon  2008-09-18 05:58:09  No: 140444

はじめまして。配列の長さについての質問です。

dimなりで配列を定義したとき、配列の長さはIntegerが限界になっています。
UInt64の最大数を長さに持つ配列を作りたいのですが、どうすればいいのでしょうか?
それともそれは不可能で、複数の配列を用意するなどの工夫が必要なのでしょうか。

ご教授お願いします。


Hongliang  2008-09-18 06:38:07  No: 140445

Array.CreateInstance(Type, Long()) を使えば確保できそうな気がします。
Integer の範囲外のインデックスを持つ要素の取得・設定は GetValue/SetValue で。
まあ x86 だとそもそもそんなでかい配列作れないですけど。


紅閃光  URL  2008-09-18 08:54:00  No: 140446

Integerというと
2^(16-1)=32,768 なのか
2^(32-1)=2,147,483,648 なのか

そもそもUInt64と言っている時点で
2^64=18,446,744,073,709,551,616
が要求されていたり。

どのような用途で使用するのか激しく興味が沸いてしかたありません。
仮に実現できたとしても使用方法をよく考えないとえらいことになりそうな・・・

配列の要素数にIntegerがOKならば多次元配列にして逃げる?
  Dim 廃列(32768, 32768, 32768)
とか・・・(注:未調査)

これが許されるなら
Int16なら 2^45 =35,184,372,088,832
Int32なら 2^93 =9,903,520,314,283,042,199,192,993,792
まではいけるかな?
あれ?次元数って3つ以上行けたっけ?
もうなにがなにやら(;・∀・)

あとはクラスの中でうまいことやるぐらいしか・・・

あぁ、なんかデジャヴュを感じる・・・


紅閃光  URL  2008-09-20 03:02:29  No: 140447

とりあえずVB6で確認してみました。

配列は 2^31 でオーバーフローします。
(2^31)-1 はオーバーフローしませんが、メモリ不足といわれて起動できません。
このメモリ不足は実行環境によるのかもしれません。

とりあえず、Int32つまり符号付32ビット整数型が上限ということですね。

あるときのわたしの仕事用パソコンでは、以下は全てOKでした。(仕事しろよ)
(べき乗数を増やすとNG・・・まぁ、倍になりますからね)
    Dim 廃列(2 ^ 27) As Integer
    Dim 廃列(2 ^ 26) As Long
    Dim 廃列(2 ^ 25) As Double
    Dim 廃列(2 ^ 17, 2 ^ 10) As Integer
    Dim 廃列(2 ^ 16, 2 ^ 10)) As Long
    Dim 廃列(2 ^ 15, 2 ^ 10)) As Double
    Dim 廃列(2 ^ 7, 2 ^ 10, 2 ^ 10) As Integer
    Dim 廃列(2 ^ 6, 2 ^ 10, 2 ^ 10) As Long
    Dim 廃列(2 ^ 5, 2 ^ 10, 2 ^ 10) As Double

Integer=2バイト 
Long=4バイト
Double=8バイト
ということを考えると、どれもだいたい 2^28バイト = 268,435,456バイト はOKとなっています。
    Dim 廃列(2 ^ 5, 2 ^ 5, 2 ^ 5, 2 ^ 5, 2 ^ 5, 2 ^ 1) As Integer
ただし、この場合は 2^27バイトしか確保できませんでした。
おそらくメモリアライメントに隙間があるせいかなと思います。

たぶん環境依存なので細かい数字はキニシナイ!

そしてフォームで確保しても、標準モジュールで確保しても、publicでもprivateでも大きな違いはないようです。
次元数はメモリが確保できる範囲では20次元でも平気でした。
あくまでもデータ量による模様。
限度はあるでしょうが。

また、さきほどは1個だけの配列変数でしたが、複数宣言した場合はまた面白い現象が見えました。
    Dim 廃列1(2 ^ 27) As Integer
    Dim 廃列2(2 ^ 27) As Integer

これはダメでしたが(メモリ不足で)、

    Dim 廃列1(2 ^ 27) As Integer
    Dim 廃列2(2 ^ 26) As Integer
    Dim 廃列3(2 ^ 26) As Integer
    Dim 廃列4(2 ^ 26) As Integer

これはOKでした。
まぁ、起動にすばらしく時間はかかりますが。

なんにしろ、1個の配列で保持できる数は、どのような型や次元であっても次元×要素数はInt32個までということは間違いようです。
VB6では。
.NETだとInt32なのかInt64なのか分かりませんが、どちらにしろUInt64はダメっぽいかな?
クラスを作るなど別の方法を考える必要があるようですね。

例えば、Public Function Get廃列Data(En As Long, Pn As Long, Gn As Long, Mn As Long, kn As Long, n As Long)
とかにしておいて、
1,152,921,504,606,846,976 のデータにアクセスするなら、

ret = Get廃列Data(1, 152, 921, 504, 606, 846, 976)

とかね。
そもそもインデックスの数値自体が型の範疇に収まらないようなw

.NETなら 変数をUInt64型で宣言できるのかな?
Array.CreateInstance(Type, Long=Int64[]) が使えたとしても、各次元の要素数は Int32.MaxValue が上限とのことなので、Integerが上限っぽいね。

落ち着いて考えたらクラスを使っても変数で2^64個のデータを保持する箱を確保するのは不可能に近いw

とりあえず逃亡。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加