当前位置:   article > 正文

数据的存储_补码截断

补码截断

1. 整型

整型包括long long, long, int, short, char, unsigned int, unsigned long long.....

整型在内存中以二进制补码的形式存储


先说有符号负整数,它最复杂

eg:

int a = -1;

原码:1000 0000 0000 0000 0000 0000 0000 0001(最高位的1表示正负,1为负,0为正)

反码:1111 1111 1111 1111 1111 1111 1111 1110

补码:1111 1111 1111 1111 1111 1111 1111 1111

从例子中可以看出,一个有符号的负数是这样在内存中存储的

首先写出-1的二进制编码,这个二进制编码就是原码

然后对原码进行按二进制位取反,得到反码

最后将反码加1,这样就得到了-1在内存中的补码,也就是-1的存储形式

再看有符号正整数和无符号整数

对于正整数,它的原码,反码,补码一样

对,就是这么简单,你只需要将一个正整数的二进制编码写出来,这个编码就是补码

那,了解这些有什么用呢?

看这个

 输出结果可不是-1,而是255

为什么是255,而不是其他的数呢?

关于这个问题,就要用到数据的存储的知识了

首先对于-1,在内存中的补码是

1111 1111 1111 1111 1111 1111 1111 1111 

再将-1存入a中,a又是unsigned char类型,大小为1个字节,8个比特位,于是-1的补码先截断成8个字节,得到新的补码:1111 1111,又由于无符号整型原,反,补码相同,则1111 1111也为原码,将其变为十进制编码,就是255,因此输出的就是255

再看一个

 这是糊涂蛋写的代码(没错就是我),这个代码死循环了,其实很好理解,unsigned是无符号,不可能为负数,因此for的条件恒为真,但是为什么0 - 1的结果是4294967295呢?

其实啊,和上一题的原因一样,0 - 1本得到的是-1,-1的补码是

1111 1111 1111 1111 1111 1111 1111 1111

当被解读成无符号数时,这个编码就是原码,算一下就是这个4294967295(2的32次方-1)


2.浮点型 

浮点型可就比整型复杂多了

就拿 float 这个短一点的举例吧

  S,1比特位           E,8比特位                 M,23比特位
浮点数在内存中的二进制编码可以这么表示
(-1)^S * 2^E * M
其中S为符号位,表示正负(1为负,0为正),E为指数部分(稍后还要讨论),M为小数部分
1)首先对于常规情况:E不为全1,也不为全0(加了中间值127后)
这种情况E有个中间值,是127,真实的E总是要先加上这个数,再转化位二进制数存入内存中
eg:
float f = 5.5;
5.5的二进制数是:101.1(这个转化过程在这里不讨论)
变为(-1)^S * 2^E * M的形式:(-1)^0 * 2 ^ 2 * 1.011
此时E的真实值为2,于是2 + 127 = 129,129就是E存入它对应8个比特位中的值,化为二进制
1000 0001
而对于M来说,由于它的整数部分恒为1,因此这个1不存入内存,这样可以提高精度,故M存入它对应的23为比特位中的二进制编码是
0110 0000 0000 0000 0000 000
S位的话就是0
于是f = 5.5 在内存中的二进制编码是
0 1000 0001 0110 0000 0000 0000 0000 000
2) 对于E为全0
这个时候的浮点数就是一个无穷小数(非常接近0), E的真实值是1 - 127(不是0 - 127啊,别搞错了,这样规定的,我也没办法),而M还原时也不用加上1了。这样做是为了表示正负0以及接近0的数
3) 对于E全为1
此时如果M的内存编码全为0,则表示正负无穷大
对于double,和float有区别的是它的E和M的位数以及E的中间数
double的E有11位,M有52位,中间数为1023
其实这个中间数有个计算公式:bias = 2^(k - 1) - 1,k为E的二进制位数

就写这么多吧,累了,一中午没睡,希望大家多多点赞评论

谢谢嘞!

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号