假设我有几个变量,如苹果,橙子,香蕉
我有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);
但是,当我输入随机数字时,它似乎不起作用。
答案 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)
这种包装是惯例。
在你的例子中
age 获取剩余的可用位(如果签名则为23位,如果不是则为24位,对于Java中的int
&LT; -age-&GT;&LT; -gender-&GT;&LT; -height-&GT;
如果使用随机数,则可能会溢出条目的有限大小(由约定定义)。例如,如果为 height 设置128,则强制性别 LSb(右位)为1
。