【问题标题】:Cross-over two integers bitwise按位交叉两个整数
【发布时间】:2026-01-29 14:00:02
【问题描述】:

我目前正在尝试实现一个非常简单的遗传算法示例。

在某一时刻,你必须用两个数字(父母)做一个“交叉”(生物学)才能得到一个“孩子”。

你可以在这里找到 CrossOver 的解释:

How to "crossover" two strings (1234 & abcd -> 12cd & ab34)

(第二个插图,更简单的“单点”交叉是我正在尝试做的。)

染色体(父母和孩子)是数字,但“交叉”将是一个位操作。

我找到了一个“染色体”的解决方案,如下所示:

  • 将位 X 向右移动(>>> 运算符)
  • 然后将位再次移动 X 个位置,但这次向左移动(<< 运算符)

所以这将保留其中一条染色体的末端并用 0 填充开头。

但我真的不知道如何解决另一条染色体的问题,然后也做交叉。

(当我保留染色体的开头/结尾并用 0 填充其余部分时,可能是 XOR。)

或者我什至应该从另一个角度解决这个问题?

【问题讨论】:

  • 您是否总是知道您的两个输入作为数字有多大(例如,16 位整数)?
  • 是的,它们总是 16 位整数。可以修改的一件事是交叉百分比。例如,75% 将保留父 A 的前 4 (25%) 位,然后在这 4 位之后使用来自父 B 的 12 (75%) 位。

标签: javascript bit-manipulation genetic-algorithm


【解决方案1】:

如果交叉的分数是 p(例如,p = .25),那么这应该有效:

mask1 = ((0xffff >> 16*p) << 16*p)
mask2 = 0xffff ^ mask1
output1 = (input1 & mask1) ^ (input2 & mask2)
output2 = (input1 & mask2) ^ (input2 & mask1)

几个注意事项:

  • 这只是伪代码。您可能需要一些演员表。
  • 这对 p 的处理不同于您在上面的评论中对它的处理。 (只需将 p 替换为 1-p 即可得到您对 p 的定义。)

【讨论】:

  • 哇,头脑=炸了!我需要一些时间来理解这段代码。 ^^ 感谢您的快速回答!
  • 好吧,将 0xffff 模式向右移动然后向左移动与您在描述中所做的相同,因此如果您的 p = .5,您的 mask1 将在右移后最终变为 0xff,然后在左移后返回 0xff00。与 0xffff 进行异或运算可以获得 mask2 中未打开的所有位。
  • 谢谢你的解释!
【解决方案2】:

一种天真的方法是使用 4 个局部变量:

int chromatid1Start;
int chromatid1End;
int chromatid2Start;
int chromatid2End;

然后,将传入的chromatid1 分配给前两个变量,将chromatid2 分配给最后两个变量。

chromatid1Start = chromatid1;
chromatid1End = chromatid1;
chromatid2Start = chromatid2;
chromatid2End = chromatid2;

Start 染色单体变量执行右移直到交叉点,然后左移完全相同的量。在End 染色单体变量上,左移到交叉点,然后右移完全相同的量。

chromatid1Start = (chromatid1Start >> 16 * crossoverPercent) << 16 * crossoverPercent;
chromatid1End = (chromatid1End << 16 * (1 - crossoverPercent)) >> 16 * (1 - crossoverPercent);
chromatid2Start = (chromatid2Start >> 16 * crossoverPercent) << 16 * crossoverPercent;
chromatid2End = (chromatid2End << 16 * (1 - crossoverPercent)) >> 16 * (1 - crossoverPercent);

这样,您可以将一个的开头与另一个的结尾交叉:

int daughterChromatid1 = chromatid1Start + chromatid2End;
int daughterChromatid2 = chromatid2Start + chromatid1End;

【讨论】: