C# 结构和数组

C# 结构和数组,c#,arrays,struct,C#,Arrays,Struct,我目前正在研究: 这是一些经过修改的代码: struct Chromosome { public bool[] genes; public int fitness; } 我从未在我的进化算法/遗传算法中使用过结构。在结构中使用数组不是有点毫无意义吗?尤其是当我必须进行深度复制时?在这种情况下使用结构有什么好处吗 谢谢。在这种情况下,布尔数组不会自动进行深度复制。因此,您并没有真正受益于structs,因为当您将染色体分配给一个新的染色体时,两个染色体中的引用都指向同一个boo

我目前正在研究:

这是一些经过修改的代码:

struct Chromosome
{
    public bool[] genes;
    public int fitness;
}
我从未在我的进化算法/遗传算法中使用过结构。在结构中使用数组不是有点毫无意义吗?尤其是当我必须进行深度复制时?在这种情况下使用结构有什么好处吗


谢谢。

在这种情况下,布尔数组不会自动进行深度复制。因此,您并没有真正受益于structs,因为当您将染色体分配给一个新的染色体时,两个染色体中的引用都指向同一个bool[]

你可以用一个数字来代替bool[],比如说
int
。基因=3的染色体代表基因:0000 0011。基因=42134的染色体代表基因:0000 0000 1010 0100 1001 0110。int是32位,这意味着您可以用这种方式表示带有232个基因的染色体。 您不必担心深度复制阵列,这在内存消耗方面也更快、更高效。如果需要更多的基因,请使用Int64

更新: 顺便说一句,你的问题很酷。如果你对某些片段中可能的基因组合有限制,你需要根据限制逐字节构造Int32。为了说明这一点,我假设了一个对染色体的一些限制的例子,并随机地对一条染色体进行了变异,但与限制有关

        //The following creates a random chromosome with restrictions
        //to the genes as described in the following:

        //Let's say that the following pattern must be adhered to: 
        //byte 1 = xxxx xxxx (anything)
        //byte 2 = 1011 xxxx (restricted)
        //byte 3 = [0000 or 1111] xxxx (restricted)
        //byte 4 = 0000 1111 (fixed value)

        Random rnd = new Random();
        byte[] randomByte = new byte[1]; //xxxx xxxx xxxx xxxx

        byte restrictedByte2 = 
            (byte)(Math.Pow(2,7) * 1 + Math.Pow(2,6) * 0 + 
            Math.Pow(2,5) * 1 + Math.Pow(2,4) * 1 + 
            rnd.Next(0, 16)); //1011 xxxx

        //in byte 3, the first (most significant) for bits are restricted to either 0000 or 1111. 
        //That's either number 0 * 16 = 0 or number 15 * 16 = 240. I multiplied by 2^4 because it's shifted
        //4 bytes to the left.
        byte higherBits = (byte)(rnd.Next(0, 2/*upper bound exclusive*/) == 1?240:0);
        //random lower bits (xxxx).
        byte lowerBits = (byte)(Math.Pow(2,0) * rnd.Next(0, 2) + Math.Pow(2,1) * rnd.Next(0, 2) + 
            Math.Pow(2,2) * rnd.Next(0, 2) + Math.Pow(2,3) * rnd.Next(0, 2) + 
            rnd.Next(0, 16));

        byte restrictedByte3 = (byte)(lowerBits + higherBits);

        byte restrictedByte4 = 143; //constant

        //Create an Int32 from the four bytes.
        int randomMutation = BitConverter.ToInt32(
            new byte[] { randomByte[1], restrictedByte2, restrictedByte3, restrictedByte4 }, 0);

在这种情况下,布尔数组不会自动进行深度复制。因此,您并没有真正受益于structs,因为当您将染色体分配给一个新的染色体时,两个染色体中的引用都指向同一个bool[]

你可以用一个数字来代替bool[],比如说
int
。基因=3的染色体代表基因:0000 0011。基因=42134的染色体代表基因:0000 0000 1010 0100 1001 0110。int是32位,这意味着您可以用这种方式表示带有232个基因的染色体。 您不必担心深度复制阵列,这在内存消耗方面也更快、更高效。如果需要更多的基因,请使用Int64

更新: 顺便说一句,你的问题很酷。如果你对某些片段中可能的基因组合有限制,你需要根据限制逐字节构造Int32。为了说明这一点,我假设了一个对染色体的一些限制的例子,并随机地对一条染色体进行了变异,但与限制有关

        //The following creates a random chromosome with restrictions
        //to the genes as described in the following:

        //Let's say that the following pattern must be adhered to: 
        //byte 1 = xxxx xxxx (anything)
        //byte 2 = 1011 xxxx (restricted)
        //byte 3 = [0000 or 1111] xxxx (restricted)
        //byte 4 = 0000 1111 (fixed value)

        Random rnd = new Random();
        byte[] randomByte = new byte[1]; //xxxx xxxx xxxx xxxx

        byte restrictedByte2 = 
            (byte)(Math.Pow(2,7) * 1 + Math.Pow(2,6) * 0 + 
            Math.Pow(2,5) * 1 + Math.Pow(2,4) * 1 + 
            rnd.Next(0, 16)); //1011 xxxx

        //in byte 3, the first (most significant) for bits are restricted to either 0000 or 1111. 
        //That's either number 0 * 16 = 0 or number 15 * 16 = 240. I multiplied by 2^4 because it's shifted
        //4 bytes to the left.
        byte higherBits = (byte)(rnd.Next(0, 2/*upper bound exclusive*/) == 1?240:0);
        //random lower bits (xxxx).
        byte lowerBits = (byte)(Math.Pow(2,0) * rnd.Next(0, 2) + Math.Pow(2,1) * rnd.Next(0, 2) + 
            Math.Pow(2,2) * rnd.Next(0, 2) + Math.Pow(2,3) * rnd.Next(0, 2) + 
            rnd.Next(0, 16));

        byte restrictedByte3 = (byte)(lowerBits + higherBits);

        byte restrictedByte4 = 143; //constant

        //Create an Int32 from the four bytes.
        int randomMutation = BitConverter.ToInt32(
            new byte[] { randomByte[1], restrictedByte2, restrictedByte3, restrictedByte4 }, 0);

通常,我们使用
struct
来表示可以认为非常原始的东西,它应该是一个表示单个“值”、16字节或更小大小的类型,以此类推

使用
struct
时要记住的主要事情是值类型语义,因此将其传入和传出函数将创建一个副本。就成本而言,这不会太糟糕,因为您要复制的是1个引用(指向bool数组)和1个int,但是如果您尝试在另一个方法或从副本中修改数组引用,它确实会产生一些有趣的副作用

许多人认为
struct
总是比
class
更有效,但情况并非总是如此,通常这种微优化是危险的,而不是有用的,因为它引入了使用值类型的副作用

对于
bool
的数组,您可以在
int
中创建和设置位,或者使用BCL中的
BitArray
专用类


因此,它的长短是,如果这是遗留代码,并且您希望保留
结构
,那么它可以工作,但如果您希望它在传递/复制时像
一样工作,它可以为您创建字节。然而,从它所持有的东西来看,它不符合MSDN指南中关于结构最适合的东西的要求。

通常,我们使用结构来表示可以认为非常原始的东西。

,它应该是一个表示单个“值”、16字节或更小大小的类型,以此类推

使用
struct
时要记住的主要事情是值类型语义,因此将其传入和传出函数将创建一个副本。就成本而言,这不会太糟糕,因为您要复制的是1个引用(指向bool数组)和1个int,但是如果您尝试在另一个方法或从副本中修改数组引用,它确实会产生一些有趣的副作用

许多人认为
struct
总是比
class
更有效,但情况并非总是如此,通常这种微优化是危险的,而不是有用的,因为它引入了使用值类型的副作用

对于
bool
的数组,您可以在
int
中创建和设置位,或者使用BCL中的
BitArray
专用类


因此,它的长短是,如果这是遗留代码,并且您希望保留
结构
,那么它可以工作,但如果您希望它在传递/复制时像
一样工作,它可以为您创建字节。然而,从它所持有的东西来看,它不符合MSDN关于结构最适合的东西的指南。

我认为这没有任何问题。。。 在GAs中,它的全部内容是验证候选人的适合性。结构只是封装了候选人的所有信息。因此,健康与你的基因直接相关。将其存储在同一个类/结构中非常有意义

如果你没有用你的基因来存储适合度,你就必须以某种方式来映射它。这将是一个不必要的麻烦。或者,如果您根本不想存储适合度,那么每次比较两个候选项时都必须重新计算它。这是不明智的。特别是当适应度评估相当复杂时(例如,在GA中评估模拟的最佳参数)

我会使用