python负数的二进制存储问题
python负数的二进制存储和获取
1.python的数据可以是无限位的,但是存储的时候是有限的。
但是计算机存储的时候会对数据进行截断,保存为32位的
python正数是按源码存储的,1的源码是0b1,
负数是按照补码存储的,如-1的补码(即源码取反再加一)是0xff…ffffff(无数个f)
2. 实际保存/截断后的存储码
如果这个数字在-2^31到2*31-1之前,则对它进行截断(去掉多余的f),舍去此数字 32 位以上的数字:&0xffffffff。
这样-1就变成了0x00…000ffffffff
注:~(ans ^ 0xffffffff) 表示对变量ans与十六进制数0xffffffff进行按位异或操作后,再对结果取按位取反。
具体解释如下:
0xffffffff是一个32位的十六进制数,其所有位均为1。在二进制表示中,它就是32个1。
当这个数用在有符号整数(如int类型)上时,由于最高位为1,它代表负数。在补码表示法中,0xffffffff实际上等同于-1。
^是C++中的按位异或操作符。它将两个操作数的对应位进行比较,如果相同则结果为0,不同则结果为1。
~是按位取反操作符,它会将操作数的每一位都取反,即将所有的0变成1,将所有的1变成0。
综上所述,~(ans ^ 0xffffffff)这个表达式通常用于对变量ans进行按位取反操作,并在此基础上加1(因为异或了-1)。这通常是为了将一个数值变为其补码表示的负数形式。例如,如果ans是一个无符号整数,那么这个操作会返回ans的补码表示的负值。
即:
32位时 1 的源码是0b1,
32位时 -1的补码为 0x00…000ffffffff
3、 怎么从截断的存储码判断存储码是正数还是负数呢?
首先可以这样 (a&0x8000 0000)>>31,如果是1,就是负数
或者可以这样 a <= 0x7fffffff,如果为False,就是负数
4 该怎么从截断的存储码得到存储码的大小呢?
经过&0xffffffff之后(如:1&0xffffffff , -1&0xffffffff),
x = 1&0xffffffff :正数的32位源码和负数的32位补码,正数可以直接输出了;
x = -1&0xffffffff:负数还需要-(~x+1),取反加一得到源码,然后再加个负号就得到所需负数了。
总结(从截断的补码,获取真实值):
方法1:获取符号,解出原码,加上符号
方法1:从截断的补码,获取真实值
m = -234 # 原数据无限位数
mm = m&0xffffffff #模拟32位计算机存储的数据,32之上的截断了 0b11111111111111111111111100010110
# 下面是计算机恢复真实数据的过程
if (mm&0x80000000)>>31&1 == 1: # 判断正负
print("负数")
print(-(((mm & 0xffffffff) ^ 0xffffffff) + 1)) # 先获取原码(按位取反+1),再加上符号
else:
print("正数", mm & 0xffffffff)
方法2:恢复32位前的值
方法2: 从截断的补码,获取真实值
m = -234 # 原数据
mm = -234 & 0xffffffff # 32位计算机所存储的截断的补码
print(bin(mm))
print(~(mm ^ 0xffffffff))
几个问题
注意 8和 8内存存储的位数不一样
因为正数没有符号的影响,但是负数有符号位,如果截断了python就无法识别它真实值
正数和负数存储的位数不一样
负数
print(bin(-0b1000 & 0xffffffff)) # 0b11111111111111111111111111111000
print(bin(-8 & 0xffffffff)) # 0b11111111111111111111111111111000
正数
print(bin(8 & 0xffffffff)) # 0b1000
print(bin(0b1000 & 0xffffffff)) # 0b1000
python 如何将一个负数的截断码转化成补码
取反+1
~(ans ^ 0xffffffff) 表示对变量ans与十六进制数0xffffffff进行按位异或操作后,再对结果取按位取反。
具体解释如下:
0xffffffff是一个32位的十六进制数,其所有位均为1。在二进制表示中,它就是32个1。
当这个数用在有符号整数(如int类型)上时,由于最高位为1,它代表负数。在补码表示法中,0xffffffff实际上等同于-1。
^是C++中的按位异或操作符。它将两个操作数的对应位进行比较,如果相同则结果为0,不同则结果为1。
~是按位取反操作符,它会将操作数的每一位都取反,即将所有的0变成1,将所有的1变成0。
综上所述,~(ans ^ 0xffffffff)这个表达式通常用于对变量ans进行按位取反操作,并在此基础上加1(因为异或了-1)。这通常是为了将一个数值变为其补码表示的负数形式。例如,如果ans是一个无符号整数,那么这个操作会返回ans的补码表示的负值
如何恢复一个数值的前32位的数
答:~(ans ^ 0xffffffff)
为什么说python是不区分有符号和无符号的
如果你截断了,python的print函数默认都是正数
参考
1、https://blog.csdn.net/qq_42759716/article/details/126431283
2、https://www.acwing.com/solution/content/47424/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端