原码、反码与补码以及数据在内存中的编码

本文介绍了原码、反码和补码的概念,以及它们在8位数表示中的数值范围和特点。原码和反码主要问题在于只能表示255个数字且0的编码不唯一,而补码解决了这些问题,能够表示256个数字并确保减法计算正确。此外,文章还探讨了数据在内存中的表示,特别是整数和浮点数在IEEE754标准下的编码方式,包括浮点数的小数二进制编码原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、原码、反码与补码

原码:最高位为符号位,8位数表示的数据最大指为127=0b0111 1111,最小值为-127=0b1111 1111,数值范围-127~127,能表示255个数字,其中10000000和00000000都表示0。
反码:正数的反码是原码,负数的反码是原码除符号位外各位取反,8位数表示的数据最大值127=0b01111111,最小值为-127=0b10000000,数值范围-127~127,能表示255个数字,其中1111 1111和0000 0000都表示0。
补码:正数的补码为原码,负数的补码为原码除符号位外各位取反(也就是反码)再加1,8位数表示的数据最大值为127=0b0111 1111,最小值为-128=0b1000 0000,数值范围-128~127,能表示256个数字,0000 0000表示0,且表示唯一。

原码的缺点:只能表示255个数字;0编码不唯一;计算减法结果不正确,如4-4=0b10000100+0b00000100=0b10001000。

反码同样只能表示255个数字且0的编码不唯一,通常做为计算补码的中间码,也就是负数的补码等于它的反码加1。

补码可以表示256个数字且0的编码唯一,也能保证减法计算结果正确,如4-4=0b0000 0100+0b1111 1100=0b1 0000 0000=0

补码的计算:负数X的补码为2^N+X的原码,如8位数N=8时,-128=2^8+(-128)=128,128的原码为0b1000 0000。

2、数据在内存中的编码

接下来看下不同数据类型在内存中的表示形式

对于整数,直接用补码表示,如
char -4=0b1111 1100=0xFC
int -4=0xFFFFFFFC

对于浮点型数据,不同标准的编码表示也不一样,最常用的是IEEE754标准,在该标准中浮点数的编码组成如下

float型:1位符号域(sign)+8位指数域(exp)+23位小数域(frac)
double型:1位符号域(sign)+11位指数域(exp)+52位小数域(frac)

这里涉及到小数的二进制编码,小数的二进制编码计算方法与整数的相反,整数是通过不断除以2来得到二进制编码

小数则是不断乘以2,然后取整数位得到一个二进制序列,如将0.4转为二进制

0.4*2=0.8 取0 余0.8
0.8*2=1.6 取1 余0.6
0.6*2=1.2 取1 余0.2
0.2*2=0.4 取0 余0.4
0.4*2=0.8 取0 余0.8
0.8*2=1.6 取1 余0.6

所以0.4的二进制表示为(0.)011001......,这里可以无限循环下去,小数的二进制表示一般都有精度要求,达到该精度后面的位就可以截断,这也就是小数无法完全精确表示的原因。

以-0.4为例分别看下float和double两种类型的补码表示

(1)float型

直观的表示整数部分和小数部分应该是

-0.0110 0110 0110 0110 0110 0110 0110 0110 ......

符号域:sign=1

指数域:指数域是指移动小数点使得小数点左边为1,此时小数点移动的位数,往左为正往右为负,这里需要往右移动2位,也就是-2,但最终还要加上2^(E-1)-1的偏移值,其中E为指数域的位数(float为8,double为11)(这里就不详细说了,可以自己去看这个标准的说明) 所以指数位是exp=125=0b01111101

小数域:小数域是小数点移动后小数点右边的数据(-1.1001 1001 1001 1001......),frac=0b1001 1001 1001 1001......

合起来就是0b1011 1110 1100 1100 1100 1100 1100 1100......=0xBECCCCCD(因为第33位是1,所以往前进1,最后一个就变成了D)。

从内存中读取值时只要将小数域frac前加上1,然后以1后的位置为基准移动exp-127位就可以分别得到整数部分和小数部分,然后根据符号位判断正负数就可以通过计算得到该编码表示的浮点数据。

(2)double型

同样的方法double型的编码表示

sign=1

exp=0111 1111 101

frac=1001 1001 1001 1001 1001 1001 1001 1001 ......

合起来就是0b1011 1111 1101 1001 1001......=0xBFD999999999999A

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值