是否有python模块允许我将数字存储在比int
小得多的对象中?
我的内存对于我的某些数据结构来说还不够大,所以我想用尽可能少的空间来表示数字。
问题是我将值存储在树结构中:
所有整数都是键或值。也许那么当使用较小的变量时,实际尺寸不会减少很多 - 我不知道。
答案 0 :(得分:3)
尽管我理解你关于numpy的最后评论,但你使用的是树状结构。
您始终可以使用整数数组来存储树。
例如:
index 0 = root 1 5
0 1 2 3 4 5 .... 15
+-------------------------------------------------------+
| 10 | 5 | 1 || ...... |
+-------------------------------------------------------+
| | ^ ^
| +----+ |
+------------------------------+
在这个例子中,每个条目都存储在数组的三个条目中,第一个条目是值,其他条目是子节点的(相对乘以3)索引。
因此,您可以在array
中存储任何树状数据结构。
唯一的问题是,使用引用编程要复杂一点。
此外,当你的"指针"具有不同的大小(例如,您需要> 65k条目 - 您将需要32位整数)您必须使用更大的大小。当然,您也可以将这三个值存储在两个甚至三个数组中。只需制作3个数组,一个用于值(例如只有16位),两个用于引用。在这种情况下,您不需要自己进行任何乘法,因为您的索引将与这些数组中的正常数组索引相同。
顺便说一句:我也猜测,你的胜利会很低,当你用numpy
实现它时,让你的树中的每个条目都是一个数组本身或使用只包含一个值的小对象,因为Python对存储在系统中的任何对象都有很大的开销。但是当你使用像示例中的少量数组时,每个数组都是一个对象,并且由于你将许多条目存储在少量数组中,所以开销是可以忽略的。
答案 1 :(得分:2)
查看numpy
数组:
>>> import numpy as np
>>> np.array([0, 1, 2, 127, -128], dtype='int8')
array([ 0, 1, 2, 127, -128], dtype=int8)
例如, np.int8
可为最高2**7 - 1
的有符号整数提供有效存储空间。
警告:超出范围的值将“环绕”而不会出现任何溢出错误:
>>> np.int8(128)
-128
当然,还有其他dtype
- s适合您,取决于您需要的值范围。
答案 2 :(得分:2)
您的任务显然是针对某些2B
- 值的内存轻量级足迹。
python
中的解决方案还有一些需要考虑的事项。
假设值的范围,满足2B
范围内int
- s(一系列数字0..65535
)所代表的值范围,以实现内存效率只是一种幻觉。
您的设计至少应考虑与对象"内部表示"相关联的间接费用。 +与对象实例的访问方法相关联的开销,以得到一个数字"那里"和"返回" (不是谈论性能影响,因为您的需求主要集中在低内存占用,但更聪明的是代理数据结构,通常会增加数据结构访问/维护CPU成本)。
如果您的主要动机是设计低内存足迹,那么最坏情况应该总结所有这些静态内存分配+访问方法期间所要求的任何动态分配的要求。 ;和对象修改'操作+ import
- ed模块大小的大小。
一旦谈到numpy
- 一个很棒的工具 - 你会得到一个伟大的&用于快速矢量化数组操作的强大库,具有给定的单元数据表示(dtype = numpy.uint8
)。
隐藏部分(对代码设计低内存占用的任何假设)是考虑方法的总体内存成本。
不仅要比较对象大小,还要比较与类相关的开销(为清晰起见,未显示大量的numpy方法列表)
>>> anIntOBJECT= 8
>>> anIntOBJECT.__sizeof__() # ____________________________instance-method works
12
>>> sys.getsizeof(anIntOBJECT) # kindly do not modify the MCVE with erroneous code
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> dir(anIntOBJECT)
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> len( dir( anIntOBJECT ) ) # Class-methods
64
使用基于字符串的数据表示的另一种方法:
>>> aStrOBJECT = "08"
>>> aStrOBJECT.__sizeof__() # ____________________________instance-method works
23
>>> sys.getsizeof(aStrOBJECT) # kindly do not modify the MCVE with erroneous code
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> dir( aStrOBJECT )
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> len( dir( aStrOBJECT ) )
71
可变序列的另一个主要原型:
>>> aBytearrayOfINTs = bytearray() # in python base
>>> aBytearrayOfINTs.__sizeof__() # _________________________instance-method works
24
>>> dir( aBytearrayOfINTs )
['__add__', '__alloc__', '__class__', '__contains__', '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'capitalize', 'center', 'count', 'decode', 'endswith', 'expandtabs', 'extend', 'find', 'fromhex', 'index', 'insert', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'pop', 'remove', 'replace', 'reverse', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> len( dir( aBytearrayOfINTs ) )
76
在所有情况下,数据结构访问/维护方法将是一个决定因素,可能更多,而不仅仅是单值(最小表示)内存占用期望。
答案 3 :(得分:1)
numpy
答案很好。另一个更简单的替代方法是在stdlib中使用array
模块。
>>> import array
>>> array_of_ints = array.array("I")
>>> sys.getsizeof(array_of_ints)
28L