《C语言编程魔法书:基于C11标准》——2.3 浮点数在计算机中的表示

简介:

本节书摘来自华章计算机《C语言编程魔法书:基于C11标准》一书中的第2章,第2.3节,作者 陈轶,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.3 浮点数在计算机中的表示

当前主流处理器一般都能支持32位的单精度浮点数与64位的双精度浮点数的表示和计算,并且能遵循IEEE754-1985工业标准。现在此标准最新的版本是2008,其中增加了对16位半精度浮点数以及128位四精度浮点数的描述。C语言标准引入了一个浮点模型,可用来表达任意精度的浮点数,尽管当前主流C语言编译器尚未很好地支持半精度浮点数与四精度浮点数的表示和计算。关于C语言标准对浮点数的描述,我们稍后将在5.2节做更详细的介绍。

为了更好地理解IEEE754-1985中规格化(normalized)浮点数的表示法,我们先来介绍一下浮点数用一般二进制数的表示方法。一个浮点数包含了整数部分和尾数(即小数)部分。整数部分的表示与我们之前所讨论过的一样,第n位就表示2n,n从0开始计。而尾数部分则是第m位表示2-m,m从1开始计。对于一个0101.1010的二进制浮点数对应十进制数的计算如图2-7所示:

image

图2-7中,整i位即表示第i位整数;尾i位即表示第i位尾数。其中,第3位整数为最高位整数;第4位尾数表示最低位尾数。对二进制浮点数的表示有了概念之后,我们就可以看IEEE754-1985标准中对规格化浮点数的描述了。IEEE754-1985对32位单精度与64位双精度两种精度的浮点数进行描述。32位单精度浮点可表示的数值范围在±1.18×10-38到±3.4×1038,大约含有7位十进制有效数;64位双精度浮点可表示的数值范围在±2.23×10-308到±1.80×10308,大约含有15位十进制有效数。我们看到IEEE定义的浮点数的绝对值范围可以是一个远大于1的数,也可以是一个大于零但远小于1的数,即它的小数精度是可浮动的,所以称之为浮点数。如果说是定点数的话,它也可表示一个小数,但是其整数位数与小数位数的精度都是固定的。比如一个16.16的定点数表示整数部分采用16个比特,尾数部分也采用16个比特。而对于一个32位浮点数来说,既能使用16.16的格式,也能使用30.2的格式(即30个比特表示整数,2个比特表示尾数)或其他各种形式。而IEEE754-1985对规格化单精度浮点数的格式如下定义:

1)1位符号位,一般是最高位(31位),表示正负号。0表示正数,1表示负数。
2)8位指数位,又称阶码,位于23到30位。(阶码的计算后面会详细介绍。)
3)23位尾数,位于0到22位。

我们下面举一个实际的例子来详细说明一个十进制小数5.625如何表示成IEEE754标准的规格化32位单精度浮点数。

1)5.625是一个正数,所以符号位为0,即第31位为0。
2)我们将5.625依照图2-7那样写成一般小数的表示法——0101.101。
3)我们将此二进制浮点数用科学计数法来表示,使得二进制整数位为最高位的1。这里最高位为1的比特是从左往右数是第二个比特,所以将小数点就放到该比特的后面,得到1.01101×22。二进制数的科学记数法,底数的值显然就是2。
4)此时,我们能看到尾数部分是小数点后面的那串二进制数,即01101,而指数为2。现在我们来求阶码。阶码用的是中经指数偏差(exponent bias)处理后的指数,即用上述得到的指数加上偏差值所求得的和。IEEE754在单精度浮点中规定,偏差值为127。所以本例中,阶码部分为2+127=129,用二进制数表示就是1000 0001。
5)尾数部分从大到小照抄,低位的用0填充即可,所以这里的尾数部分二进制数为:011 0100 0000 0000 0000 0000。
6)将整个处理完的二进制数串起来获得:0(符号位)1000 0001(阶码)011 0100 0000 0000 0000 0000(尾数),用十六进制数表达就是:40B4 0000。

十进制小数转64位双精度浮点数的方法与上述雷同,只不过阶码用11位比特来表示,尾数则用52位比特表示,而偏差值则规定为1023。

相关文章
|
1月前
|
存储 编译器 C语言
【C语言】数据类型全解析:编程效率提升的秘诀
在C语言中,合理选择和使用数据类型是编程的关键。通过深入理解基本数据类型和派生数据类型,掌握类型限定符和扩展技巧,可以编写出高效、稳定、可维护的代码。无论是在普通应用还是嵌入式系统中,数据类型的合理使用都能显著提升程序的性能和可靠性。
50 8
|
2月前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
78 4
|
3月前
|
NoSQL C语言 索引
十二个C语言新手编程时常犯的错误及解决方式
C语言初学者常遇错误包括语法错误、未初始化变量、数组越界、指针错误、函数声明与定义不匹配、忘记包含头文件、格式化字符串错误、忘记返回值、内存泄漏、逻辑错误、字符串未正确终止及递归无退出条件。解决方法涉及仔细检查代码、初始化变量、确保索引有效、正确使用指针与格式化字符串、包含必要头文件、使用调试工具跟踪逻辑、避免内存泄漏及确保递归有基准情况。利用调试器、编写注释及查阅资料也有助于提高编程效率。避免这些错误可使代码更稳定、高效。
557 12
|
3月前
|
C语言
初识C语言:与计算机的交流之输入与输出(scanf和printf)
初识C语言:与计算机的交流之输入与输出(scanf和printf)
297 0
|
3月前
|
存储 程序员 编译器
初识C语言,计算机语言的基石
初识C语言,计算机语言的基石
|
4月前
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
4月前
|
Linux C语言
C语言 多进程编程(七)信号量
本文档详细介绍了进程间通信中的信号量机制。首先解释了资源竞争、临界资源和临界区的概念,并重点阐述了信号量如何解决这些问题。信号量作为一种协调共享资源访问的机制,包括互斥和同步两方面。文档还详细描述了无名信号量的初始化、等待、释放及销毁等操作,并提供了相应的 C 语言示例代码。此外,还介绍了如何创建信号量集合、初始化信号量以及信号量的操作方法。最后,通过实际示例展示了信号量在进程互斥和同步中的应用,包括如何使用信号量避免资源竞争,并实现了父子进程间的同步输出。附带的 `sem.h` 和 `sem.c` 文件提供了信号量操作的具体实现。
|
1月前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
70 10