我们可以存储少于4个字节的整数吗?

时间:2015-05-19 17:49:30

标签: java arrays optimization int byte

据我所知,在Java中使用short,我们可以存储最小值-32,768,最大值为32,767(含)。 使用int我们可以存储最小值-2 ^ 31和最大值2 ^ 31-1
问题:如果我有一个int[] numbers,我可以存储的数字是正数高达10万 是否有可能以某种方式存储这些数字而不必为每个使用4个字节?我想知道是否有特定的"小"范围可能有一些" hack / trick"这样我就可以使用比numbers.length*4

更少的内存

3 个答案:

答案 0 :(得分:2)

您可以尝试使用屏蔽或位操作来表示每个数字,然后如果您希望获得完整的位数,则稍后执行符号扩展。这种操作是在当今几乎所有计算机系统中的系统架构级别上完成的。

它可能会帮助你研究2's Complement,这似乎是你想要的......而且可能Sign Extension可以用来衡量。

通常,在高级语言中,int由处理器寄存器的基本大小表示。 ex)8,16,32或64位。

如果您使用2-Complement方法,则可以根据需要轻松考虑所有正数和负数。这在硬件上也很容易,因为您只需要反转所有位然后再加1,这可能会比其他可能的方法提供更大的性能提升。

2的补语如何运作

  • 通过反转所有位来获取-N然后 加1

即,获得N的1补码,然后加1。

For example with 8-bit words:
 9 = 00001001
-9 = 11110111 (11110110 + 1)

在硬件中轻松高效 (反向然后+1)
•n位字可用于表示数字 从-2 ^(N-1)到+(2 ^(N-1) - 1)


更新:用于表示更大数字的位操作
如果你试图得到一个更大的数字,比如评论中的1,000,000,那么你可以使用按位左移操作然后通过以2的适当幂增加当前数字来提取数字。

    9 (base 10): 00000000000000000000000000001001 (base 2)
                  --------------------------------
9 << 2 (base 10): 00000000000000000000000000100100 (base 2) = 36 (base 10)

您还可以尝试: 的Zero-fill right shift

该运算符将第一个操作数向右移位指定的位数。向右移位的多余位被丢弃。零位从左侧移入。符号位变为0,因此结果始终为非负数。

对于非负数,零填充右移和符号传播右移产生相同的结果。例如,9 >>> 2 yields 2,与9 >> 2相同:

9 (base 10): 00000000000000000000000000001001 (base 2)
                   --------------------------------
9 >>> 2 (base 10): 00000000000000000000000000000010 (base 2) = 2 (base 10)

然而,负数不是这种情况。例如,-9 >>> 2 yields 1073741821,与-9 >> 2不同(产生-3):

-9 (base 10): 11111111111111111111111111110111 (base 2)
                    --------------------------------
-9 >>> 2 (base 10): 00111111111111111111111111111101 (base 2) = 1073741821 (base 10)

正如其他人在评论中所述,如果你试图操纵非特定字/双/等对齐的数据,你实际上可能会长期妨碍你的整体表现。这是因为你的硬件必须更加努力才能尝试拼凑你真正需要的东西。

答案 1 :(得分:1)

一种解决方案是使用位操作并使用您选择的多个位来存储单个数字。假设您选择使用5位。然后,您可以在4个字节中存储4个这样的数字。当需要进行操作时,您需要将位打包并解压缩为整数。

你需要决定是否要处理负数,在这种情况下你需要存储一个符号位。

为了更容易使用,您需要创建一个类,通过get和store操作来隐藏细节。

鉴于有关表现的问题,通常情况下,我们正在为表现交易空间,反之亦然。根据具体情况,可以使用各种优化技术来最小化CPU周期数。

那就是说,首先需要这样的优化吗?如果是这样,它是在内存级别还是存储级别?我们可以使用压缩等通用机制来处理这种情况而不是使用特殊技术吗?

答案 2 :(得分:1)

只是另一个想法。一个参数是您拥有的数字范围。但其他属性也可以帮助节省存储空间。例如,当您知道每个数字可以被8的某个倍数整除时,您不需要存储低3位,因为您知道它们始终为0。 (这是JVM存储&#34;压缩&#34;引用的方式。)

或者,采取另一种可能的方案:当您存储素数时,所有这些(2除外)都将是奇数。所以不需要存储最低位,因为它总是1.当然你需要单独处理2。在浮点表示中使用了类似的技巧:由于非空数的尾数的第一位始终为1,因此根本不存储,因此将精度提高1位。