【问题标题】:Bit manipulation on large integers out of 'int' range对超出“int”范围的大整数进行位操作
【发布时间】:2016-04-28 13:52:03
【问题描述】:

好的,让我们从一个 32 位整数开始:

int big = 536855551; // 00011111111111111100001111111111

现在,我想将最后 10 位设置在这个整数内:

int little = 69; // 0001101001

所以,我的方法是这样的:

big = (big & 4294966272) & (little)

4294966272 是前 22 位,或 11111111111111111111110000000000

当然,这不受支持,因为4294966272 超出了0x7FFFFFFFint 范围。此外,这不会是我唯一的操作。我还需要能够设置位 11 到 14。我的方法(有同样的问题)是:

big = (big & 4294951935) | (little << 10)

因此,在解释完之后,我正在做的就是替代上述内容:

1: ((big >> 10) << 10) | (little)
2: (big & 1023) | ((big >> 14) << 14) | (little << 10)

我不觉得我的替代方案是我可以采用的最好、最有效的方法。有没有更好的方法来做到这一点?

旁注:如果 C# 支持二进制字面量,'0b',这会更漂亮。

谢谢。

【问题讨论】:

  • 使用 BigInteger .....?
  • 旁注:对于公共源代码,请使用十六进制表示法或显式位移 (10xFFFFFC00 时,我不知道有谁能够将 4294966272 转换为他们头中的位。
  • @AlexeiLevenkov 我发现二进制文件更容易阅读。尤其是当我的重点是设置特定位时。所以不,当我的主要关注点是位时,我不会使用十六进制表示。

标签: c# int bit-manipulation 32-bit uint32


【解决方案1】:

4294966272实际上应该是-1024,表示为11111111111111111111110000000000

例如:

int big = 536855551; 
int little = 69;
var thing = Convert.ToInt32("11111111111111111111110000000000", 2);
var res = (big & thing) & (little);

虽然,结果总是0

00011111111111111100001111111111
&
00000000000000000000000001101001
&
11111111111111111111110000000000

【讨论】:

  • 我喜欢这个,因为我可以将掩码定义为常量,而且看起来不错。它的工作方式与我的方法完全相同,但有名称。
【解决方案2】:

与位移 + 掩码(即 &)相比,位移通常更快。我有一个test case

你应该选择你的第一个选择。

1: ((big >> 10) << 10) | (little)

当涉及到位移时,请注意 a little difference 介于无符号和有符号 int 之间。

或者,您可以将biglittle 定义为无符号。使用uint 而不是int

【讨论】:

  • 这是一个可以接受的答案,但如果我将掩码定义为常量,Rob 会更漂亮。速度确实很重要,但这并不重要。它的工作原理就像我尝试在我的方法中所做的那样,但有名字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多