Python float 精度浮点数
Python float precision float
我需要实施一个动态规划算法来及时解决旅行商问题,以击败蛮力搜索来计算点之间的距离。为此,我需要按大小索引子问题,每个子问题的值将是一个浮点数(游览的长度)。但是,如果我使用 python 浮点数(实际上具有双精度),将数组保存在内存中将占用大约 6GB RAM,因此要尝试将该数量减半(我只有 4GB RAM),我将需要使用单精度浮点数.但是我不知道如何在 Python 中获得单精度浮点数(我正在使用 Python 3)。有人能告诉我在哪里可以找到它们吗(我在互联网上找不到太多)。谢谢
编辑:我注意到 numpy 也有一个 float16 类型,可以节省更多内存。点之间的距离大约为 10000,并且有 25 个不同的点,我的答案需要是最接近的整数。 float16 会提供足够的精度还是我需要使用 float32?
您可以尝试 ctypes
标准库中的 c_float
类型。或者,如果您能够安装其他包,您可以尝试 numpy
包。它包括 float32
类型。
作为第一步,您应该使用 NumPy 数组而不是 Python 列表来存储数据。
正如您正确观察到的那样,Python 浮点数在内部使用双精度,并且 Python 浮点数下的双精度 value 可以表示为8 个字节。但是在 64 位机器上,使用 Python 的 CPython 参考实现,一个 Python float
object 需要一个完整的24 字节内存:8 字节用于底层双精度值,8 字节用于指向对象类型的指针,8 字节用于引用计数(用于垃圾回收)。在 Python 中没有 Java 的 "primitive" 类型或 .NET 的 "value" 类型的等价物——一切都被装箱了。这使语言语义更简单,但意味着对象往往更胖。
现在,如果我们要创建 Python list 个 float
个对象,则会增加列表本身的开销:一个 8 字节对象每个 Python float
的指针(这里仍然假设是 64 位机器)。所以一般来说,n
Python float
对象的列表将花费你超过 32n
字节的内存。在 32 位机器上,情况稍微好一些,但也好不了多少:我们的 float
个对象将每个占用 16 个字节,而对于列表指针,我们将使用 20n
个字节的内存对于长度为 n
的 float
的列表。 (警告:如果您的列表引用来自多个列表索引的 same Python float
对象,则此分析不太有效,但这不是特别常见的情况。)
相比之下,n
双精度浮点数的 NumPy 数组(使用 NumPy 的 float64
dtype)将其数据以 "packed" 格式存储在 [=23] 的单个数据块中=] 字节,因此考虑到数组元数据,总内存需求将略高于 8n
字节。
结论:只需从 Python 列表切换到 NumPy 数组,您的内存需求就会减少大约 4 倍。如果这还不够,那么考虑减少精度从双精度到单精度(NumPy 的 float32
dtype),如果这符合您的精度需求。 NumPy 的 float16
数据类型每个浮点数只占用 2 个字节,但只记录大约 3 个小数位的精度;我怀疑它对于您描述的应用程序来说几乎毫无用处。
我需要实施一个动态规划算法来及时解决旅行商问题,以击败蛮力搜索来计算点之间的距离。为此,我需要按大小索引子问题,每个子问题的值将是一个浮点数(游览的长度)。但是,如果我使用 python 浮点数(实际上具有双精度),将数组保存在内存中将占用大约 6GB RAM,因此要尝试将该数量减半(我只有 4GB RAM),我将需要使用单精度浮点数.但是我不知道如何在 Python 中获得单精度浮点数(我正在使用 Python 3)。有人能告诉我在哪里可以找到它们吗(我在互联网上找不到太多)。谢谢
编辑:我注意到 numpy 也有一个 float16 类型,可以节省更多内存。点之间的距离大约为 10000,并且有 25 个不同的点,我的答案需要是最接近的整数。 float16 会提供足够的精度还是我需要使用 float32?
您可以尝试 ctypes
标准库中的 c_float
类型。或者,如果您能够安装其他包,您可以尝试 numpy
包。它包括 float32
类型。
作为第一步,您应该使用 NumPy 数组而不是 Python 列表来存储数据。
正如您正确观察到的那样,Python 浮点数在内部使用双精度,并且 Python 浮点数下的双精度 value 可以表示为8 个字节。但是在 64 位机器上,使用 Python 的 CPython 参考实现,一个 Python float
object 需要一个完整的24 字节内存:8 字节用于底层双精度值,8 字节用于指向对象类型的指针,8 字节用于引用计数(用于垃圾回收)。在 Python 中没有 Java 的 "primitive" 类型或 .NET 的 "value" 类型的等价物——一切都被装箱了。这使语言语义更简单,但意味着对象往往更胖。
现在,如果我们要创建 Python list 个 float
个对象,则会增加列表本身的开销:一个 8 字节对象每个 Python float
的指针(这里仍然假设是 64 位机器)。所以一般来说,n
Python float
对象的列表将花费你超过 32n
字节的内存。在 32 位机器上,情况稍微好一些,但也好不了多少:我们的 float
个对象将每个占用 16 个字节,而对于列表指针,我们将使用 20n
个字节的内存对于长度为 n
的 float
的列表。 (警告:如果您的列表引用来自多个列表索引的 same Python float
对象,则此分析不太有效,但这不是特别常见的情况。)
相比之下,n
双精度浮点数的 NumPy 数组(使用 NumPy 的 float64
dtype)将其数据以 "packed" 格式存储在 [=23] 的单个数据块中=] 字节,因此考虑到数组元数据,总内存需求将略高于 8n
字节。
结论:只需从 Python 列表切换到 NumPy 数组,您的内存需求就会减少大约 4 倍。如果这还不够,那么考虑减少精度从双精度到单精度(NumPy 的 float32
dtype),如果这符合您的精度需求。 NumPy 的 float16
数据类型每个浮点数只占用 2 个字节,但只记录大约 3 个小数位的精度;我怀疑它对于您描述的应用程序来说几乎毫无用处。