整数和浮点数在内存中的存储

一、整数在内存中的存储

整数在内存中的存储方式有三种:原码、反码和补码。

正整数的原码、反码、补码都相同。

负整数的三种表示方法各不相同。

原码是整数的二进制表示形式。正整数的原码就是其二进制表示形式,负整数的原码则是其二进制表示形式做数值位,首位(符号位)设为1。

反码是将原码的符号位不变,其它位按位取反得到的。

补码是反码加上 1。在计算机中,整数一般以补码的形式存储。补码可以方便地进行加减运算。

补码可以方便地进行加减运算,主要有以下两个原因:

  • 补码的加法和减法运算规则相同

在补码中,正数的补码与原码相同,负数的补码是原码取反加 1。因此,对于两个补码数,其加法运算规则与原码的加法运算规则相同。减法运算可以通过加法运算来实现,即将被减数的补码与减数的补码的相反数相加。

  • 补码可以用相同的硬件实现加减运算

在原码中,加法和减法运算需要使用不同的硬件电路。在补码中,加法和减法运算可以使用相同的硬件电路,这简化了硬件设计和实现。

例如,

正整数 5 的原码、反码和补码都是 00000000 00000000 00000000 00000101

负整数 -5 的原码是 10000000 00000000 00000000 00000101,反码是 11111111 11111111 11111111 11111010,补码是 11111111 11111111 11111111 11111011

整数在内存中的存储大小取决于其位数。例如,32 位整数在内存中占 4 个字节,64 位整数在内存中占 8 个字节。

二、浮点数在内存中的存储

1. 浮点数的表示

在C语言中,浮点数通常用floatdouble类型表示。这两种类型的主要区别在于它们的精度和范围。float类型通常有32位,而double类型有64位。

浮点数在内存中的表示遵循IEEE 754标准。这个标准定义了浮点数的二进制表示,包括符号位、指数部分和尾数部分。

2. IEEE 754标准

IEEE 754标准定义了浮点数的二进制表示,

任意一个二进制浮点数V可以表示成下面的形式:

V=(-1)^{^{S}}*M*2^{E}

(-1)^{^{S}} 表示符号位:S为0时V为正数,S为1时V为负数。

M 表示有效数字,M是大于等于1,小于2的。

2^{E} 表示指数位

我们来看看如何表示十进制的3.14和-3.14。

对于3.14:

  1. 符号位S=0,因为3.14是正数。
  2. 将3.14转换为二进制,得到的近似值是11.0010001111010111000010100011110
    (二进制小数点后面的位数可以根据需要进行截断)。

    首先,将整数部分3转换为二进制。3的二进制表示为11。

    接下来,将小数部分0.14转换为二进制。我们可以通过乘以2的方式将小数部分转换为二进制。具体步骤如下:

    0.14 * 2 = 0.28  (整数部分为0)
    0.28 * 2 = 0.56  (整数部分为0)
    0.56 * 2 = 1.12  (整数部分为1)
    0.12 * 2 = 0.24  (整数部分为0)
    0.24 * 2 = 0.48  (整数部分为0)
    0.48 * 2 = 0.96  (整数部分为0)
    0.96 * 2 = 1.92  (整数部分为1)
    0.92 * 2 = 1.84  (整数部分为1)
    0.84 * 2 = 1.68  (整数部分为1)
    0.68 * 2 = 1.36  (整数部分为1)
    0.36 * 2 = 0.72  (整数部分为0)
    0.72 * 2 = 1.44  (整数部分为1)
    0.44 * 2 = 0.88  (整数部分为0)
    0.88 * 2 = 1.76  (整数部分为1)
    0.76 * 2 = 1.52  (整数部分为1)
    0.52 * 2 = 1.04  (整数部分为1)
    0.04 * 2 = 0.08  (整数部分为0)
    0.08 * 2 = 0.16  (整数部分为0)
    0.16 * 2 = 0.32  (整数部分为0)
    0.32 * 2 = 0.64  (整数部分为0)
    0.64 * 2 = 1.28  (整数部分为1)
    0.28 * 2 = 0.56  (整数部分为0)
    0.56 * 2 = 1.12  (整数部分为1)
    0.12 * 2 = 0.24  (整数部分为0)
    0.24 * 2 = 0.48  (整数部分为0)
    0.48 * 2 = 0.96  (整数部分为0)

    可以观察到,小数部分不断乘以2,将整数部分取出,直到小数部分为0或者达到所需的精度。

    将整数部分和小数部分合并在一起,就得到了3.14的二进制表示:

    3.14(十进制) = 11.0010001111010111000010100011110(二进制)


  3. 将这个二进制数转换为科学计数法,得到1.10010001111010111000010100011110 * 2^1。
  4. 所以,M=1.10010001111010111000010100011110,E=1。

对于-3.14:

  1. 符号位S=1,因为-3.14是负数。
  2. 将-3.14的绝对值转换为二进制,得到的近似值是11.0010001111010111000010100011110。
  3. 将这个二进制数转换为科学计数法,得到1.10010001111010111000010100011110 * 2^1。
  4. 所以,M=1.10010001111010111000010100011110,E=1。

【注】由于二进制表示的限制,这些值只是近似值,可能会有一些微小的误差。此外,实际的存储还涉及到指数的偏移和尾数的规格化等处理,这里为了简化说明,暂时忽略了这些处理步骤。

对于32位的float类型,其结构如下:

  • 符号位(Sign):1位
  • 指数部分(Exponent):8位
  • 尾数部分(Fraction):23位

对于64位的double类型,其结构如下:

  • 符号位(Sign):1位
  • 指数部分(Exponent):11位
  • 尾数部分(Fraction):52位

3. 浮点数存的过程

指数部分表示的是2的幂,它属于unsigned int类型。在float类型中,指数部分是8位,范围是0到255。在double类型中,指数部分是11位,范围是0到2047。但是科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数(8位的E,中间数是127;11位的E,中间数是1023)

尾数部分表示的是浮点数的实际值。这部分的值被视为一个小于1的正数,前面加上1(即1.xxxx)。这样做的目的是为了增加精度。比如保存1.01时,只保存01,等到读取时再加上1作为第一位。以32位浮点数为例,将第一位的1舍去后,留给M的就有23+1=24位有效数字。

4. 浮点数取的过程

(1)E不全为0或E不全为1

此时,将E的计算值减去127或1023,得到真实值,再将有效数字M前加上第一位的1。

 示例

让我们来看一个例子。假设我们有一个float类型的数,其二进制表示为:

01000001001101100000

我们可以将这个二进制数分解为三部分:

  • 符号位:0
  • 指数部分:10000010(十进制表示为130)
  • 尾数部分:01101100000

根据IEEE 754标准,我们可以计算出这个浮点数的值为:

(-1)^0 * 2^(130-127) * 1.01101100000 = 6.421875
(2)E全为0

此时,E的真实值等于1-127或1-1023,有效数字M前无需加上第一位的1。

这种情况是为了表示\pm0,以及十分接近于0的数字。

(3)E全为1

此时,如果有效数字M全为0,表示正负无穷大(正负取决于符号位S)。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值