将多个整数连接成一个更大的整数

4

我有一个深夜脑死问题。它可能很简单,但你知道,在编程8小时+后接近最后期限时会怎样。:)

这是我的问题...

我有一个长度为10的布尔数组,逻辑上分成几个部分来保存4个不同的整数位数组(作为布尔值)。这是目标数组:

bool[] myArray = new bool[10]; 

以下是我想要插入的4个整数:

int value1 = 3;  // 2 bits, myArray[0-1], 11
int value2 = 12; // 4 bits, myArray[2-5], 1100
int value3 = 2;  // 2 bits, myArray[6-7], 10
int value4 = 1;  // 2 bits, myArray[8-9], 01

myArray应该最终看起来像下面这样(注意第一个元素是位置0):

{(T,T),(T,T,F,F),(T,F),(F,T)}

最终我想要做的是将myArray转换为一个整型值:

0x1111001001 = 969

也许有更好的方法可以在不使用布尔值的情况下完成这个操作?因此,让我用更一般的方式重新表达我的问题:
如何将N个int值“连接”成一个目标int?
谢谢!

1
不是答案,但我认为更适合您的工具是BitArray类。 - Steve
我不明白为什么 value4(即 1)会贡献 两个 位,即 01。我认为它应该只给出 一个 位?如果每个 int 值根据其大小贡献了 0 到 31 个位,编码可能会很有趣。 - Jeppe Stig Nielsen
@Jeppe 即使 value4 等于 1,它也需要 2 位,因为它可以是从 0 到 3 的任意值。在我的例子中,我只是使用了值 1。 - Jan Tacci
@JanTacci 如果是这样,那么我的下面的回答可能不适合您。因为我的答案并没有硬编码位长度 2;4;2;2。相反,它总是采用最短的可能位长度。因此,它不会像您要求的那样返回固定长度的位模式(10=2+4+2+2)。 - Jeppe Stig Nielsen
2个回答

1
通常,将来自多个数字的位组合成一个数字的常见方法是这样的(以您的值和位长度为例):

var result = value1 | (value2 << 2) | (value3 << 6) | (value4 << 8);

然而,你在问题末尾打印的数字是反过来的。如果这就是你想要的,那么正确的顺序应该是:

var result = value4 | (value3 << 2) | (value2 << 4) | (value1 << 8);

当然,这假定代码知道每个值所需的位长度。如果您在编译时不知道位长度,则必须在运行时跟踪它,否则像1这样的单个int将无法告诉您的代码从中使用多少位。

我知道目标中每个元素所需的位长度! - Jan Tacci
不,你的回答很清楚。我说了什么让你觉得有所不同吗? - Jan Tacci
@JanTacci:谢谢。:) 不用了,我刚才看错了你的评论 :) - Timwi
@JanTacci 但是我理解的问题并没有得到解决。对于每个int值,取其二进制表示,去掉前导零,然后与下一个项目连接起来也不行。 - Jeppe Stig Nielsen
@JeppeStigNielsen:他的示例中的value4有一个前导零,他希望保留它。 - Timwi
@Timwi 是的,我找到了。所以这是一个完全“传统”的任务,其中宽度是预先确定的。但解决“错误”的问题仍然很有趣(这是我在答案中尝试做的)。 - Jeppe Stig Nielsen

0

这里尝试编写代码,将整数的二进制表示连接起来,其中二进制表示中没有前导零。

static int Concat(int high, int low)
{
  // find location i of most significant bit of "low"
  int i;
  for (i = 31; i > -1; --i)
    if ((low & (1 << i)) != 0)
      break;

  if (i == 31)
    return low;
  return low & (high << (i + 1));
}

static int ConcatMany(IEnumerable<int> values)
{
  return values.Aggregate(Concat);
}

应该这样使用:

int concatOfTwoNumbers = Concat(3, 12);

var list = new List<int> { 3, 12, 2, 1, };
int concatOfList = ConcatMany(list);

当然,如果连接中有超过32位,则最高有效位将“掉落”到左侧。要与64位整数一起使用,请将highlow更改为long,并将两个31更改为63


@JanTacci 我意识到我的回答不是你想要的。请看我对你原来问题的新评论。但即使只是误解了你的问题,解决“我的”问题也很有趣。另外请注意,使用我的“连接”方法,你无法从“总和”中重构出各个值,因为一旦进行了连接,就无法确定各个“部分”(值)之间的“边界”在哪里。 - Jeppe Stig Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接