14

我有两个整数,我需要传递一个整数,然后取回两个整数的值。

我正在考虑使用逻辑运算符(AND、OR、XOR 等)。

4

5 回答 5

15

使用 C 编程语言,假设两个整数小于 65535,可以如下完成。

void take2IntegersAsOne(int x)
{
   // int1 is stored in the bottom half of x, so take just that part.
   int int1 = x & 0xFFFF;  

   // int2 is stored in the top half of x, so slide that part of the number
   // into the bottom half, and take just that part.
   int int2 = (x >> 16) & 0xFFFF

   // use int1 and int2 here. They must both be less than 0xFFFF or 65535 in decimal

}


void pass2()
{
  int int1 = 345;
  int int2 = 2342;
  take2Integers( int1 | (int2 << 16) );
}

这依赖于在 C 中一个整数存储在 4 个字节中的事实。因此,该示例使用前两个字节来存储其中一个整数,接下来的两个字节用于存储第二个。这确实施加了限制,尽管每个整数都必须具有足够小的值,以便它们每个都适合 2 个字节。

移位运算符 << 和 >> 用于上下滑动整数的位。移动 16 位,将位移动两个字节(因为每个字节有 8 位)。

使用 0xFFFF 表示数字的低两个字节中的所有位都是 1 的位模式因此,ANDing(使用 & 运算符)导致不在这两个低字节中的所有位被关闭(回到零)。这可用于从您当前提取的整数中删除“其他整数”的任何部分。

于 2011-01-19T17:31:19.483 回答
6

这个问题有两个部分。首先,如何将两个 32 位整数位掩码为一个 64 位长整数?

正如其他人所说,假设我有一个函数,它采用 X 和 Y 坐标,并返回一个表示该点的线性值的 longint。我倾向于称这种二维数据的线性化:

public long asLong(int x, int y) {
    return ( ((long)x) << 32 ) | y;
}

public int getX(long location) {
    return (int)((location >> 32) & 0xFFFFFFFF);
}

public int getY(long location) {
    return (int)(location & 0xFFFFFFFF);
}

如果我对操作顺序有偏执,请原谅我,有时其他操作比 << 更贪婪,导致事情发生了超出应有的变化。

为什么这行得通?什么时候可能失败? 整数往往恰好是 longint 大小的一半,这很方便。我们正在做的是将 x 转换为 long,将其向左移动,直到它完全位于 y 的左侧,然后执行联合操作 (OR) 以组合两者的位。

让我们假设它们是 4 位数字组合成一个 8 位数字:

x = 14     :      1110
y =  5     :      0101

x = x << 4 : 1110 0000

p = x | y  : 1110 0000
           OR     0101
             ---------
             1110 0101

同时,反过来:

p = 229    : 1110 0101  
x = p >> 4 : 1111 1110  //depending on your language and data type, sign extension
                        //can cause the bits to smear on the left side as they're
                        //shifted, as shown here. Doesn't happen in unsigned types
x = x & 0xF:
             1111 1110
         AND 0000 1111
         -------------
             0000 1110  //AND selects only the bits we have in common

y = p & 0xF:
             1110 0101
         AND 0000 1111
         -------------
             0000 0101  //AND strikes again

这种方法很久以前就出现了,在需要从存储或传输空间中挤出每一点的环境中。如果您不在嵌入式系统上或立即打包此数据以通过网络传输,那么整个过程的实用性开始迅速崩溃:

  • 仅仅对几乎总是需要立即拆箱并由调用者读取的返回值进行装箱的工作量太大了。这有点像挖一个洞然后把它填满。
  • 它大大降低了您的代码可读性。“返回什么类型?” 呃......一个int......和另一个int......在很长的时间里。
  • 它可能会引入难以追踪的错误。例如,如果您使用无符号类型并忽略符号扩展,则稍后迁移到导致这些类型成为二进制补码的平台。如果您保存 longint,并尝试稍后在代码的另一部分中阅读它,您可能会在 bitshift 上遇到一个错误的错误并花费一个小时调试您的函数,只是发现它是错误的参数。

如果情况如此糟糕,还有什么替代方案?

这就是为什么人们问你关于你的语言的原因。理想情况下,如果您使用 C 或 C++ 之类的语言,最好说

struct Point { int x; int y; };

public Point getPosition() {
    struct Point result = { 14,5 };
    return result;
}

否则,在像 Java 这样的 HLL 中,您可能会使用内部类来实现相同的功能:

public class Example {
    public class Point {
        public int x;
        public int y;
        public Point(int x, int y) { this.x=x; this.y=y; }
    }

    public Point getPosition() {
        return new Point(14,5);
    }
}

在这种情况下,getPosition 返回一个 Example.Point - 如果您经常使用 Point,请将其提升为自己的完整类。事实上,java.awt 已经有几个 Point 类,包括 Point 和 Point.Float

最后,许多现代语言现在都有语法糖,用于将多个值装箱成元组或直接从函数返回多个值。这是最后的手段。根据我的经验,任何时候你假装数据不是它样子,你最终都会遇到问题。但是,如果您的方法绝对必须返回两个根本不属于同一数据的数字,那么元组或数组就是要走的路。

c++ stdlib 元组的参考可以在 http://www.cplusplus.com/reference/std/tuple/找到

于 2012-10-22T17:05:00.390 回答
2

好吧.. @Felice 是对的,但是如果它们都适合 16 位,那么有一种方法:

output_int = (first_int << 16) | second_int
                               ^
                           means 'or'

打包它们,并且

first_int = output_int & 0xffff
second_int = (output int >> 16) & 0xffff
                                ^
                           means 'and'

提取它们。

于 2011-01-19T17:29:03.920 回答
1

两个整数不能适合一个整数,或者至少你不能取回原来的两个整数。
但无论如何,如果两个原始整数被限制在一定数量的位上,你可以(在伪代码中):第一个整数或与(第二个整数 SHIFTLEFT(nOfBits))

为了取回两个整数,用一个由 nOfBitsOne 表示的二进制数掩码合并整数,然后获得第一个整数,然后通过 nOfBits ShiftRight 合并整数,然后返回第二个整数。

于 2011-01-19T17:25:51.000 回答
-1

您可以在一个 32 位整数中存储 2 个 16 位整数。第一个是 16 个第一位,第二个是后 16 个位。要检索和组合您使用移位运算符的值。

于 2011-01-19T17:29:38.780 回答