1

C# と XNA は初めてです。三角形のグリッドを生成するクラスを作成できました。しかし、問題が 1 つあります。最大 27 ノードの長さの三角形を取得できます。28 で Out of memory 例外をスローし、31 で -overFlow 例外をスローします。

どのようにオーバーフローしたり、メモリ不足になったりするのかわかりません...これらすべてのメモリ値を計算しようとしましたが、非常に小さく見えます。

変数の影響を受けるノードの配列のみです。ノードクラスはそれほど大きくありません:

フロート x; 4 B float y; 4 B float z; 4 B int[] コン; int[6] 4*6=24 B バイトパス。1 B カラー列。32b=4B

            Total:  41B

三角形を作成するために必要なノードのシーケンス合計は n(n+1)/2 です

28でメモリ不足

28*29/2=406 ノード

合計メモリ:

41*406 = 16646B = 16.26kB

31 でオーバーフロー: 496 ノードは 19.9 kB

「メモリ不足の例外」に関する記事を読みました。構造体のサイズは見た目よりも大きく、メモリ不足は500MBのサイズで発生します...私の小さな三角形がそのような巨大なサイズに達する方法はありません。

これは私のクラス全体です:

class TriMatrix
    {
        int len;
        int Lenght;
        Node[] node;
        VertexPositionColor[] vertex;

        public class Node
        {
            public float x;
            public float y;
            public float z;
            public int[] con;
            public byte pass;
            public Color col;
            public Node(byte passable)
            {
                pass = passable;
                if (pass > 0)
                { col = Color.Green; }
                else
                { col = Color.DarkRed; }
                x = 0;
                z = 0;
                con = new int[6];
            }
        }

        public TriMatrix(int lenght)
        {
            len = lenght;
            Lenght = 0;
            byte pass;
            Random rnd = new Random();
            for (int i = 0; i <= len; i++)
            {
                Lenght += Lenght + 1;
            }
            node = new Node[Lenght];
            int num = 0;
            for (int i = 0; i < len; i++)
            {
                for (int j = 0; j <= i; j++)
                {

                    if (rnd.Next(0, 5) > 0) { pass = 1; } else { pass = 0; }
                    node[num] = new Node(pass);
                    node[num].x = (float)i - (float)j / 2.0f;
                    node[num].y = 0;
                    node[num].z = (float)j * 0.6f;
                    if (i < len - 1) { node[num].con[0] = num + i; } else { node[num].con[0] = -1; node[num].col = Color.Violet; }
                    if (i < len - 1) { node[num].con[1] = num + i + 1; } else { node[num].con[1] = -1; }
                    if (j < i) { node[num].con[2] = num + 1; } else { node[num].con[2] = -1; node[num].col = Color.Violet; }
                    if (j < i) { node[num].con[3] = num - i; } else { node[num].con[3] = -1; }
                    if (i > 0) { node[num].con[4] = num - i - 1; } else { node[num].con[4] = -1; }
                    if (i > 0) { node[num].con[5] = num - 1; } else { node[num].con[5] = -1; }
                    if (j == 0) { node[num].col = Color.Violet; }
                    num++;
                }
            }
        }

        public void Draw(Effect effect, GraphicsDevice graphics)
        {
            VertexPositionColor[] verts = new VertexPositionColor[3];
            int num = 0;
            for (int i = 0; i < len-1; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                        verts[1] = new VertexPositionColor(new Vector3(node[num + i + 1].x, node[num + i + 1].y, node[num + i + 1].z), node[num + i + 1].col);
                        verts[2] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                        graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);

                        if ( j < i)
                        {
                            verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
                            verts[1] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
                            verts[2] = new VertexPositionColor(new Vector3(node[num + 1].x, node[num + 1].y, node[num + 1].z), node[num + 1].col);
                            graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);
                        }
                    }
                    num++;
                }
            }
        }
    }// endclass
4

1 に答える 1

7

あなたのバグはこのループにあると思います(自由にスペルを修正してください):

for (int i = 0; i <= len; i++)
{
    Length += Length + 1;
}

ループ内で、 の値を1Length だけ増やしています。Lengthこれは実質的に、反復ごとに の値を 2 倍にすることを意味し、指数関数的に増加します。

最初の数回の反復では、 の値はLength1、3、7、15、31、63、… になります。反復iで の値Lengthが 2 i +1 −1になるように、このシーケンスを一般化できます。反復 28 では、これは 536,870,911 になります。反復 31 では、これは 4,294,967,295 になります。

編集:以下のコメントで述べたように、長さの三角形グリッドの要素数を計算するための正しい修正は次のようにlenなります。

for (int i = 1; i <= len; i++)
{
    Length += i;
} 

これは、三角数1 + 2 + 3 + … + lenと呼ばれるものを計算する総和と同じです。次の式を使用して簡潔に計算できます。

Length = len * (len + 1) / 2;

この数が非常に大きくなる理由は、それが平方関係であるためです。の長さの一辺のn場合、 の約半分の面積が必要です

于 2012-10-12T21:16:56.357 に答える