3 python的数值在内存中如何存储
python的数值在内存中如何存储
在Python中,数值在内存中的存储方式取决于数值的类型和大小,以及Python的版本。Python使用固定的字节数来表示整数类型,并且对于浮点数,通常使用双精度(64位)或者扩展精度(128位)的浮点表示。
整数的存储方式: 对于较小的整数,Python通常使用一个机器字长来存储它们,例如,在32位机器上,小整数通常使用32位来存储。对于较大的整数,Python使用了一种称为GMPY的机制,它使用动态大小的字节数组来存储。
浮点数的存储方式: Python使用IEEE 754标准来存储浮点数,对于64位的浮点数,Python使用1位作为符号位(E),11位作为指数位(M),52位作为尾数位(M)。
下面是一个简单的例子,演示了如何在Python中查看数值的内存表示:
import sys
def view_bytes(number, bits):
return bin(int.from_bytes(number.to_bytes(bits // 8, sys.byteorder), 'little'))[2:]
# 整数示例
i = 10
print(f"The binary representation of {i} is: {view_bytes(i, 64)}")
# 浮点数示例
f = 3.14
print(f"The binary representation of {f} is: {view_bytes(f, 64)}")
这段代码使用了sys.byteorder来确定字节顺序(大端或小端),int.from_bytes和int.to_bytes来转换整数为字节序列,并使用bin函数转换为二进制字符串。对于浮点数,它使用了相同的方法,但是浮点数需要先转换为一个双精度的浮点数。
注意:这个方法只适用于显示数值的二进制表示,并不能直接显示Python内部如何存储数值的细节。实际上,Python的内部实现可能会根据平台和Python版本的不同而有所差异。
偶然间看到float的取值范围是-3.4*10^38到3.4*10^38,然后有效位数是6位或者7位(和编译器有关),突发奇想,想知道float和double的取值范围是如何计算出来的,了解了一下,大概做个总结。
首先说一下Float
1.Float的内存结构
首先我们需要了解一下float的内存结构,弄清楚它在内存中是如何存放的。
float和整形(int等)存放的方式不一样,是以指数方式(科学计数法)的方式存储的。分为三个部分。符号位,指数部分,尾数部分,float占4个字节,总共32位,其中符号位占一位,指数占8位,尾数占23位,数字9.25的存储结构如下图所示:

符号位就是表示当前变量的正负,1正0负
这个例子的表示的float的值是:1.00101 * 2^3,也就是 1001.01,转换成10进制就是9+

=9.25,具体是为什么呢,可以往下看
指数部分
float的指数位没有符号,在内存中将指数+127存储。
图中指数部分是1000 0010,对应的十进制数是130,实际上的指数值需要减去127,也就是3,所以例子中对应的指数就是3,
所以去掉一个最大值,一个最小值,指数表达的范围是:[-126,127]
尾数部分
尾数部分占23位,但是实际上是24位1第一位1被省略,例子中9.25对应的二进制数是1001.01,

,1001.01可以写成
。我们可以发现,只要我们要存储的数值不为0,任何数都可以写成1.xxxxx

,所以我们第一位数是可以省略的,不用存储,尾数部分存储的就是小数点后面的内容,小数点也不用存储。我们存在内存中的数就是0010 1000 0000 0000.........(总共23位尾数)
如果要float变量的值为0,那就让尾数和指数全为0,以此来表示0,这是一种特殊情况。
2.float的取值范围分析
所以float的最大值最小值怎么出来呢?

指数全1的情况(255-127)为了表示特殊的值被用掉了,所以指数最大是254-127=127,尾数省略1和小数点,所以为了使尾数最大,取全1,这时候尾数 =

,这个数非常接近2,所以最后的值就是2*2^127 = 2*1.7014 E38,大概就是3.4E38左右,
最小就是将符号位变成1,表示负数,其他没有任何区别。
double的话指数长度为11位,尾数长度为52位,存储原理是一样的。
import struct # 定义一个双精度浮点数 value = 123.456 # 将浮点数转换为字节 bytes_value = struct.pack('d', value) # 打印字节表示 print(bytes_value)

浙公网安备 33010602011771号