小数在内存中是如何存储的

小数在内存中是以浮点数的形式存储的。浮点数并不是一种数值分类,它和整数、小数、实数等不是一个层面的概念。浮点数是数字(或者说数值)在内存中的一种存储格式,它和定点数是相对的。

C语言使用定点数格式来存储 short、int、long 类型的整数,使用浮点数格式来存储 float、double 类型的小数。整数和小数在内存中的存储格式不一样。

我们在学习C语言时,通常认为浮点数和小数是等价的,并没有严格区分它们的概念,这也并没有影响到我们的学习,原因就是浮点数和小数是绑定在一起的,只有小数才使用浮点格式来存储。

其实,整数和小数可以都使用定点格式来存储,也可以都使用浮点格式来存储,但实际情况却是,C语言使用定点格式存储整数,使用浮点格式存储小数,这是在“数值范围”和“数值精度”两项重要指标之间追求平衡的结果,稍后我会给大家带来深入的剖析。

计算机的设计是一门艺术,很多实用技术都是权衡和妥协的结果。

浮点数和定点数中的“点”指的就是小数点!对于整数,可以认为小数点后面都是零,小数部分是否存在并不影响整个数字的值,所以干脆将小数部分省略,只保留整数部分。
定点数

所谓定点数,就是指小数点的位置是固定的,不会向前或者向后移动。

假设我们用4个字节(32位)来存储无符号的定点数,并且约定,前16位表示整数部分,后16位表示小数部分,如下图所示:
在这里插入图片描述
如此一来,小数点就永远在第16位之后,整数部分和小数部分一目了然,不管什么时候,整数部分始终占用16位(不足16位前置补0),小数部分也始终占用16位(不足16位后置补0)。例如,在内存中存储了 10101111 00110001 01011100 11000011,那么对应的小数就是 10101111 00110001 . 01011100 11000011,非常直观。

精度:
(1)小数部分的最后一位可能是精确数字,也可能是近似数字(由四舍五入、向零舍入等不同方式得到);
(2)除此以外,剩余的31位都是精确数字。
(3) 从二进制的角度看,这种定点格式的小数,最多有 32 位有效数字,但是能保证的是 31 位;也就是说,整体的精度为 31~32 位。

数值范围
将内存中的所有位(Bit)都置为 1,小数的值最大,为 216 - 2-16,极其接近 216,换算成十进制为 65 536。将内存中最后一位(第32位)置1,其它位都置0,小数的值最小,为2-16。

这里所说的最小值不是 0 值,而是最接近 0 的那个值。

综述

用定点格式来存储小数,优点是精度高,因为所有的位都用来存储有效数字了,缺点是取值范围太小,不能表示很大或者很小的数字。
反面例子

在科学计算中,小数的取值范围很大,最大值和最小值的差距有上百个数量级,使用定点数来存储将变得非常困难。例如,电子的质量为:
0.0000000000000000000000000009 克 = 9 × 10^-28 克

太阳的质量为:
2000000000000000000000000000000000 克 = 2 × 10^33 克

如果使用定点数,那么只能按照=前面的格式来存储,这将需要很大的一块内存,大到需要几十个字节。
更加科学的方案是按照=后面的指数形式来存储,这样不但节省内存,也非常直观。这种以指数的形式来存储小数的解决方案就叫做浮点数。浮点数是对定点数的升级和优化,克服了定点数取值范围太小的缺点。

浮点数
C语言标准规定,小数在内存中以科学计数法的形式来存储,具体形式为:
flt = (-1)sign × mantissa × baseexponent

对各个部分的说明:

flt 是要表示的小数。
sign 用来表示 flt 的正负号,它的取值只能是 0 或 1:取值为 0 表示 flt 是正数,取值为 1 表示 flt 是负数。
base 是基数,或者说进制,它的取值大于等于 2(例如,2 表示二进制、10 表示十进制、16 表示十六进制……)。数学中常见的科学计数法是基于十进制的,例如 6.93 × 1013;计算机中的科学计数法可以基于其它进制,例如

1.001 × 27 就是基于二进制的,它等价于 1001 0000。
mantissa 为尾数,或者说精度,是 base 进制的小数,并且 1 ≤ mantissa < base,这意味着,小数点前面只能有一位数字;
exponent 为指数,是一个整数,可正可负,并且为了直观一般采用十进制表示。

下面我们以 19.625 为例来演示如何将小数转换为浮点格式。

当 base 取值为 10 时,19.625 的浮点形式为:
19.625 = 1.9625 × 101

当 base 取值为 2 时,将 19.625 转换成二进制为 10011.101,用浮点形式来表示为:
19.625 = 10011.101 = 1.0011101×24

19.625 整数部分的二进制形式为:
19 = 1×24 + 0×23 + 0×22 + 1×21 + 1×20 = 10011
小数部分的二进制形式为:
0.625 = 1×2-1 + 0×2-2 + 1×2-3 = 101
将整数部分和小数部分合并在一起:
19.625 = 10011.101

可以看出,当基数(进制)base 确定以后,指数 exponent 实际上就成了小数点的移动位数:

exponent 大于零,ma
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值