十六进制格式的带符号二进制转十进制

十六进制格式的带符号二进制转十进制

这个问题必须记录一下,我以为转换就是直接按位取反,但是结果总是不对,经过分析后才发现数据分析就有问题,那当然接下来怎么做都不会对了

计算方法

我们先演示流程并获取结果:

  1. 0xFFF8 转 二进制:1111 1111 1111 1000 ,这是带符号的二进制数据,首位为 1 ,因此是负数;
  2. 负数是用补码表示的,补码是原码取反+1,也就是说需要先减 1 得到:1111 1111 1111 0111
  3. 取反得到:0000 0000 0000 0000 1000,转10进制就是8,加上符号就是 -8,没错,这就是我想要的结果。

~ 操作符转换演示

$a = 0xFFF8;
$ret = ~$a;
var_dump($ret); // 输出:-65529

结果和我想要的不一样啊,那来捋一下 ~ 操作符的计算流程,我们用简单的值演示一下:

  1. 0x0005 转 二进制:0000 0000 0000 0101
  2. 取反得到:1111 1111 1111 1010, 观察取反后的结果,从左向右看,第一位 0正1负;
  3. 负数是用补码表示的,补码是除符号位外按位取反+1,也就是说 1111 1111 1111 1010 是某个数取反+1得到的,反过来,也就是先 -1,结果是:1111 1111 1111 1001
  4. 取反得到: 1000 0000 0000 0110,转10进制就是-6

看过上面的流程就可以发现啦,一直以为0xFFF8是原数,所以就作按位取反,当然结果一直不对,因为转换方式和数据分析 都是错的,数据是从硬件内存中取出直接上传的,而负数在内存中以补码形式存在,因此数据已经是补码了,再按位取反当然就不对了。

正确转换方式

$a = 0xFFF8;
$ret = $a - 0xFFFF - 1;

var_dump($ret); // 输出:-8

没错,就是这么简单!当然,这个是针对 2字节的数据的,如果是4字节,将 0xFFFF 改为 0xFFFFFFFF 就可以啦~

当然,以上纯粹针对小白。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值