将值打包成单个int

时间:2010-12-29 01:41:08

标签: java

假设我有几个变量,如苹果,橙子,香蕉

我有8个苹果,1个橙子,4个香蕉。

是否有可能以某种方式将这些值转换为单个整数,并根据计算的整数值还原为原始值?

我在网上找到了一个例子。

int   age, gender, height;
short packed_info;
. . .
// packing
packed_info = (((age << 1) | gender) << 7) | height;
. . .
// unpacking
height = packed_info & 0x7f;
gender = (packed_info >>> 7) & 1;
age    = (packed_info >>> 8);

但是,当我输入随机数字时,它似乎不起作用。

5 个答案:

答案 0 :(得分:11)

如何操作

是的,你可以这样做。执行此操作的简单方法是您现在正在执行的操作,即将整数的不同位分配给不同的值。你的是这样的,对于一个32位的int:

|3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1     |      |             |
|1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 |  7   |6 5 4 3 2 1 0|
|                     Age                        |Gender|   Height    |

当您将值8移位到右侧时,您只需要使用数字的年龄部分。如果你向右移位七并用1屏蔽它,即value >>> 7 & 1,那么你就会得到性别。如果你只是掩盖了最后七位(即value & 0x7F),那么你就得到了高度。

为什么它很脆弱

您的示例缺少重要的内容:值的范围。例如,高度值永远不会高于127.如果您尝试存储128或更高的高度,那么您现在编写它的方式将导致部分高度覆盖性别,因为您需要8位存储一个大的值。这就是随机数不起作用的原因。

同样地,如果有人意外地输入了不是零或一的性别,那么它会使部分年龄值变得混乱,因为你只是无法存储一个高位的数字

在分配中修复此问题的方法是插入位掩码,如下所示:

packed_info = (((age << 1) | (gender & 1)) << 7) | (height & 0x7f);

当这样做时,你可以确定性别不会覆盖年龄,高度不会覆盖其他人。但是,如果你的高度大于127,它将被用于mod 127。

为什么你通常不应该

因为它容易出错并且整数不会占用太多内存。你不能只记得它是int,你需要记住位布局的样子。保持三个int s更容易。

然而,当传输速度很重要时,这种事情仍然存在。 (例如,数字电视或其他视频,数字音频,以太网协议等)

答案 1 :(得分:1)

首先:你的想法很好,你的转移不正确(或者你有这样做的危险)。

那就是说,这更像是一个数学问题,而不是一个Java问题,但让我们一起玩:)。

你可以将任意数量的整数打包成一个整数,假设数字可以无限增长,例如:

(设n为结果数,n1 ... nk为数字,Pn为第n个素数)

n = 2^n1 + 3^n2 + 5^n3 ... Pn^nk

现在,这是行不通的,因为拆包很慢,你不能打包大号或大量的。

无论采用何种技术,您都会遇到这样的问题:您的数字越大,数字越多,打包就越难。

我要去哪里?您可以使用按位打包或任何其他类型的打包,只要整数中存在空间来保存您的信息即可。您使用的按位逻辑就可以了!

答案 2 :(得分:1)

您可以打包和解压缩签名值。例如,在一个中打包两个:

int pack2(int val1, int val2)
{
    int ret_val = (((val1 & 0xFFFF) << 16) | (val2 & 0xFFFF));
    return ret_val;
}

int[] unpack2(int packed)
{
    int val1 = ((packed >> 16) & 0xFFFF);
    // restore sign
    if ((val1 & 0x8000) != 0)
        val1 |= 0xFFFF0000;

    int val2 = (packed & 0xFFFF);
    // restore sign
    if ((val2 & 0x8000) != 0)
        val2 |= 0xFFFF0000;

    return new int[] { val1, val2 };
}

当然,您必须确保两个值都介于-0x7FFF和0x7FFF之间(如果是两个值)。

答案 3 :(得分:0)

您可以这样做,但它取决于目标整数的大小和“水果”变量的可能范围。如果范围较大,则需要不同的位域配置。某个字段所需的位数等于log_2(最大范围值)。

答案 4 :(得分:0)

这种包装是惯例

在你的例子中

  • height 是7位(从0到127)
  • 性别位于1位(0或1)
  • age 获取剩余的可用位(如果签名则为23位,如果不是则为24位,对于Java中的int

    &LT; -age-&GT;&LT; -gender-&GT;&LT; -height-&GT;

如果使用随机数,则可能会溢出条目的有限大小(由约定定义)。例如,如果为 height 设置128,则强制性别 LSb(右位)为1