`
anna_zr
  • 浏览: 200510 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

转-从一个C++笔试题看浮点数的表示

阅读更多
网上流行的一份C++笔试题目中有这样一个题目(最初出处未知,从google或者baidu可搜索到多出来源)

10. 以下两条输出语句分别输出什么?[C++难]
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?

这个题目涉及float在计算机中的存储问题, IEEE 754的标准就是描述的这个问题。如果这个题目放在笔试的时候应该比面试的时候容易多了。

这个题目的几个答案为1,1065353216(0x3f800000H),false,0,0,true。如果你已完美的答出这六个答案,就可以忽略后面的内容。

1.我们先来看一下IEEE 754中关于float,double的存储规范。
无论是单精度还是双精度在存储中都分为三个部分:

1.  符号位(Sign) : 0代表正,1代表为负

2.  指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储

3.  尾数部分(Mantissa):尾数部分

其中float的存储方式如下图所示:



指数部分(E) 占用8-bit的二进制数,可表示数值范围为0-255。 但是指数应可正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float的指数可从 -126到128.

尾数部分(M)实际是占用24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有23-bit。

符号位:s 通过(-1)的s次幂来表示正负号。

而双精度的存储方式为:



我们把E,M从二进制串表示转换为真正的e、m
这里要涉及到“规格化(normalized)”、“非规格化(denormalized)”。规格化与否全看指数E!下面分三种情况讨论E,并分别计算e和m:
1、规格化:当E的二进制位不全为0,也不全为1时,N为规格化形式。此时e被解释为表示偏置(biased)形式的整数,e值计算公式如下图所示:





上图中,|E|表示E的二进制序列表示的整数值,例如E为"10000100",则|E|=132,e=132-127=5 。 k则表示E的位数,对单精度来说,k=8,则bias=127,对双精度来说,k=11,则bias=1023。

此时m的计算公式如下图所示:





标准规定此时小数点左侧的隐含位为1,那么m=|1.M|。如M="101",则|1.M|=|1.101|=1.625,即 m=1.625

2、非规格化:当E的二进制位全部为0时,N为非规格化形式。此时e,m的计算都非常简单。




注意,此时小数点左侧的隐含位为0。   为什么e会等于(1-bias)而不是(-bias),这主要是为规格化数值、非规格化数值之间的平滑过渡设计的。后文我们还会继续讨论。有了非规格化形式,我们就可以表示0了。把符号位S值1,其余所有位均置0后,我们得到了 -0.0; 同理,把所有位均置0,则得到 +0.0。非规格化数还有其他用途,比如表示非常接近0的小数,而且这些小数均匀地接近0,称为“逐渐下溢(gradually underflow)”属性。
3、特殊数值:当E的二进制位全为1时为特殊数值。此时,若M的二进制位全为0,则n表示无穷大,若S为1则为负无穷大,若S为0则为正无穷大; 若M的二进制位不全为0时,表示NaN(Not a Number),表示这不是一个合法实数或无穷,或者该数未经初始化。

2.问题的解答
对于1.0f这个数字,我们应该如何表示?按照上面的规则可以得到,符号位为0,指数位为127(0x7F),尾数部分M应该为全0。因此它在计算机中的存储就是0x3F800000H。

cout << (int)a << endl;

把a从浮点数转换为整数,由于1.0f能够使用32bits完整的表示,没有舍入误差,因此会输出整数 1
cout << (int&)a << endl;

把a里面的内容转换为整数地址,因此编译器会直接浮点数的32位表示直接输出,,即0x3f800000h的10进制表示。

对于0.0f这个特殊的表示上面已经提到了,它在内存中的存储就是全0,因此直接把浮点数转换为整数还是直接把浮点数的表示转化为整数地址结果都是0。

正如上面提到的一样,浮点数-0的表示和+0的表示是不同的,-0在内存中的表示为0x80000000H。

最后再转载一点关于long double的知识,我也没有自己深入。

3.扩展双精度格式(long double)
⑴ 扩展双精度格式(SPARC 结构计算机)

该4倍精度浮点环境符合IEEE关于扩展双精度格式的定义。该浮点环境的4倍精度浮点格式共128位,占4个连续32位字,包含3个构成字段:112位的小数f,15位的偏置指数e,和1位的符号s。将这4个连续的32位字整体作为一个128位的字,进行重新编号。其中0:110位包含小数f;112:126位包含偏置指数e;第127位包含符号位s。如图3所示。

在SPARC结构计算机中,地址最高的32位字存放小数的32位最低有效位,即f[31:0];但是在PowerPC结构计算机中,却是地址最低的32位字存放这些位。

紧邻的两个32位字(在SPARC机中向下计算,在PowerPC机中向上计算)分别存放f[63:32]和f[95:64]。

最后一个字的第0到15位存放小数的最高16位,即f[111:96]。其中第0位存放该16位的最低有效位,第15位存放整个小数f的最高有效位。第16到30位存放15位的偏置指数e,其中第16位存放偏置指数的最低有效位,第30位存放它的最高有效位。最高位,第31位存放符号s。




⑵ 扩展双精度格式(Intel x86结构计算机)

该浮点环境双精度扩展格式符合IEEE双精度扩展格式的定义。该浮点环境的扩展双精度格式共80位,占3个连续32位字,包含四个构成字段:63位的小数f,1位显式前导有效位(explicit leading significand bit)j,15位偏置指数e,和1位符号位s。将这3个连续的32位字整体作为一个96位的字,进行重新编号。其中0:63包含63位的小数f,第63位包含前导有效位j,64:78位包含15位的偏置指数e,最高位第79位包含符号位s。

在Intel结构系计算机中,这些字段依次存放在十个连续的字节中。但是,由于 UNIX  System V Application Binary Interface Intel 386 Processor Supplement (Intel ABI) 要求双精度扩展参数,从而占用堆栈中3个相连地址的32位字,其中最高一个字的高16位未被使用。




地址最低的32位字存放小数f的低32位,即f[31:0]。其中第0位存放整个小数f的最低有效位LSB 第31位存放小数低32位的最高有效位MSB。
地址居中的32位字,第0到30位存放小数f的31位最高位,即f[62:32]。其中第0位存放31位最高小数位的最低有效位LSB,第30位存放整个小数的最高有效位,地址居中的32位字的最高位第31位存放显式的前导有效位j。

地址最高32位字里,第0到14位存放15位的偏置指数e,第0位存放偏置指数的最低有效位LSB,第14位存放最高有效位MSB,第15位存放符号位s。虽然地址最高的32位字的高16位在Intel x86结构系列机种未被使用,但他们对符合Intel ABI的规定来说,是必需的。



原文地址 http://blog.csdn.net/abortexit/archive/2009/06/22/4288279.aspx 
分享到:
评论

相关推荐

    趋势科技招聘经典软件笔试题--C++

    【C++知识点详解】 ...以上是对趋势科技招聘经典软件笔试题中涉及的C++知识点的详细解答。这些题目涵盖了C++的基础语法、数据结构、内存管理、程序设计等多个方面,展示了软件工程师需要掌握的关键技能。

    C_C++笔试题大全

    根据给定的文件信息,以下是对C和C++笔试题中的关键知识点的详细解析: ### 1. Static关键字的用途 Static关键字有多种用途,在不同的上下文中有着不同的含义: - **在函数体内**:用于声明一个变量,使得该变量在...

    c++笔试题目(多看点没错)

    本文对C++笔试题目进行了详细的解析,涵盖了static关键字的作用、变量的存储域、实时系统的基本特性、平衡二叉树、堆栈溢出、虚函数、冒泡排序算法、浮点数比较、网络协议、IP地址转换、局部变量和全局变量的区别、...

    中兴通讯C++C笔试题附有答案

    根据给定的中兴通讯C++/C笔试题及其描述,我们可以提炼出多个重要的IT知识点,涵盖基础语法、数据类型处理、预处理器指令、内存管理、函数调用以及字符串操作等核心领域。下面将逐一详细解析这些知识点: ### 1. ...

    华为公司C++笔试题

    【华为公司C++笔试题】涉及的知识点广泛,包括C++语言特性、数据结构、算法、内存管理、网络协议以及编程实践。以下是这些知识点的详细解释: 1. `static` 关键字: - 在函数内部,`static` 使得变量在函数每次...

    c/c++笔试大全(含答案)

    C/C++笔试大全(含答案) 本资源摘要信息涵盖了C/C++编程语言的多个方面,包括静态变量、函数、指针、数组、数据结构、算法、网络协议等。 静态变量 在C/C++中,静态变量有多种用途。第一种是,在函数体中,静态...

    华为c++笔试题

    在华为的C++笔试中,题目通常涵盖语言的基础知识,包括运算符优先级、内存管理、类型转换、预处理器指令、函数调用以及标准库的使用。以下是对这些知识点的详细解释: 1. 表达式判断与赋值: - A 和 B 的表达式都...

    C/C++ 网络通讯笔试题大全

    【C/C++ 网络通讯笔试题大全】 在C/C++编程中,网络通讯是不可或缺的一部分,尤其在开发服务器端、客户端应用或者嵌入式系统时。以下是一些重要的知识点,结合题目中的内容进行详细解释: 1. **static的作用**: ...

    C++笔试题 百问百答

    理解这些基本概念对于解答C++笔试题至关重要,它们涵盖了命名空间的使用、头文件包含的注意事项、内存大小的查询以及与C语言接口的兼容性处理等多个方面。熟悉这些知识点不仅能帮助解决实际编程问题,也是面试和笔试...

    C/C++笔试题附答案华为面试题系列.txt

    - **指针的定义:** 指针是一个变量,它的值是另一个变量的地址。 - **指针的声明:** 声明指针时需要指定它指向的数据类型。 - **指针的运算:** 可以对指针进行算术运算(如加减操作),通常用于数组遍历等场景。 ##...

    C++笔试题-面试

    正确比较浮点数与零值,应考虑浮点数的精度问题,使用一个小的正负阈值进行判断,例如: ```cpp if (fabs(x) &gt; 0.000001) ``` ### Internet的网络协议及层次结构 Internet主要采用TCP/IP协议族,其层次结构包括:...

    华为c/c++笔试题

    【华为c/c++笔试题】涉及的知识点广泛,主要涵盖了计算机系统、数据结构、面向对象编程、C/C++语言、软件工程、操作系统、数据库系统、计算机网络和无线通信等多个领域。下面将对这些知识点进行详细解释: 1. `...

    C++笔试题(二)

    ### C++笔试题知识点解析 #### 1. 定义一个宏来比较两个数的大小,不使用大于、小于、if语句 在C++中,宏定义是一种预处理指令,用于实现简单的文本替换。本题要求定义一个宏来比较两个整数a和b的大小,但又不允许...

    华为C++笔试题..

    【华为C++笔试题】是针对想要进入华为从事软件开发的求职者准备的,这份试题主要涵盖C++语言的基础知识,包括语法、数据结构、内存管理、程序设计等多个方面。以下将对其中的关键知识点进行详细解释: 1. `static` ...

    C C++ 笔试题大全

    【C/C++笔试知识点】 1. **static的用途**: - 在函数内部,static变量在函数每次调用时保留其前一次的值,而非重新初始化。 - 在全局作用域内,static变量只能在定义它的模块内访问,提供了一种局部全局变量的...

    华为C++笔试题.doc

    在华为的C++笔试题中,涉及了C++语言的基础知识,包括`static`关键字的用途、引用与指针的区别、实时系统特性、内存管理、数据结构(如平衡二叉树)、程序性能(如时间复杂度)、网络协议、IP地址结构以及C++编程...

    C++笔试考试复习题

    ### C++笔试考试复习知识点详解 #### 一、C++源程序文件的默认扩展名 - **知识点**:C++源程序文件的默认扩展名是`.cpp`。...以上知识点覆盖了C++笔试考试复习题中的核心概念和技术细节,希望对考生有所帮助。

    C-C++语言程序设计笔试面试题.docx

    在C/C++编程中,面试和笔试题通常会涵盖语言的基础概念、内存管理、类型系统以及程序设计技巧。以下是对给定试题的详细解析: 1. **试题6 - GetMemory内存申请**: 试题6中的GetMemory函数通过传入字符串指针的...

Global site tag (gtag.js) - Google Analytics