浮点数的表示方法

来源:互联网 发布:完美红颜魂器进阶数据 编辑:程序博客网 时间:2024/04/30 06:01

计算机中浮点数的表示

never2die  长江大学湖北荆州

中文摘要:本文介绍了浮点数在计算机中的几种表示方法,并对此进行整理分析,为人们以后做此方面的研究提供参考。

中文关键词:浮点数;计算机;计算机存储;浮点数的表示

Floating Number Expression In Computer

Abstract: This paper introduced the floating number in the computer several expression method, and carries on the reorganization analysis regarding this, will later make this aspect for the people the research to provide the reference.

Key word: Floating number; Computer; Computer memory; Floating number expression

  

当今信息时代,计算机已经深入到我们生活的方方面面。笔者学习计算机多年,但很少看以有关计算机中浮点数表示的文章和书籍。经过查阅资料和总结思考,对此理出了一点头绪。

二进制不符合人们的习惯,但是计算机内部却采用二进制表示信息,其主要原因有以下几点:

电路简单:计算机是由逻辑电路组成的,逻辑电路通常只有两个状态。

工作可靠:两个状态代表两个数据,数字传输和处理不容易出错,因而电路更加可靠。

简化运算:二进制运算法则简单。

逻辑性强:计算机工作原理是建立在逻辑运算基础上的,逻辑代数是逻辑运算的理论依据。二进制只有两个数码,正好代表逻辑代数的“真”与“假”。

 

在计算机中,数据的存储和表示方法和我们平时用的是不同的。它利用了电和磁的两种极性来表示数据的不同,当然在计算机中就只有01了,而我们生活中用的都是十进制。那么我们这些十进制的数据又是怎么在计算机中存储表示的呢?

我们知道需要把十进制数转换为二进制数进行存储表示,整数转换为二进制很简单,也不会有什么误差。那么当我们要表示的是浮点数又是什么样的呢?在浮点数中,只有少量的数可以用这种方法精确的表示出来,而绝大多数是无法精确表示的。举一个简单的例子:

3.14159 我们直接对它进行转换,则为11.0010010000111111001

用这种方法我们无法把3.14159精确表示

 

我们可以用这两种方法来表示浮点数:

 

1.BCD代码。Binary-Coded Decimal‎,简称BCD,称BCD码或二-十进制代码,亦称二进码十进数。是一种二进制的数字编码形式,用二进制编码的十进制代码。这种编码形式利用了四个位元来储存一个十进制的数码,使二进制和十进制之间的转换得以快捷的进行。这种编码技巧,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

由于十进制数共有0、1、2、……、9十个数码,因此,至少需要4位二进制码来表示1位十进制数。4位二进制码共有2^4=16种码组,在这16种代码中,可以任选10种来表示10个十进制数码,共有 N=16!/(16-10)!约等于2.9乘以10的10次方种方案。常用的BCD代码列于末。

1.1  8421BCD
这种编码的特点是,若把代码看成4位二进制数,则个位数的权便依次是84,21,而且每个代码的十进制数值恰好就是它们所表示的十进制数值,其编码表如下:

十进制

0

1

2

3

4

5

6

7

8

9

二进制

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

 

1.2  余三码
8421BCD码的每个编码加上3就得到了余三码

十进制

0

1

2

3

4

5

6

7

8

9

二进制

0011

0100

0101

0110

0111

1000

1001

1010

1011

1100

 

1.3   循环码
8421BCD码的每个编码,最高位照旧,后面每一位与前一位取异或,就得到了循环码。

十进制

0

1

2

3

4

5

6

7

8

9

二进制

0000

0001

0011

0010

0110

0111

0101

0100

1100

1101

 

2.阶码尾数表示法
       这种思想来源于数学中的指数表示形式:

例如,十进制数

类似地,二进制数

2.1 浮点表示法中的尾数与阶码。对于一个R进制数,只要惟一确定MC的值( ),则该数的值就惟一确定了,

即的值就惟一确定了。因此,在计算机中,对于一个二进制的浮点数( ),只需要存储MC的值就可以了。MC分别称为尾数与阶码。尾数M为小于1的纯小数,表示方法与定点数中的纯小数表示方法相似,其长度将影响数的精度,其符号将决定数的符号;阶码C相当于数学中的指数,它是一个整数,其表示方法与定点整数的表示方法类似。

2.2 浮点数的表示形式。假定一个浮点数用4个字节来表示,则一般阶码占用一个字节,尾数占用3个字节,且每部分的最高位均用以表示该部分的正负号。

例如,在计算机内的表示形式如下:

10000011

11101100

00000000

00000000

阶码部分

尾数部分

值得一提的是,4个字节表示的浮点数的精度和表示范围都远远大于同等长度表示的定点数,这是浮点数的优越之处。但在运算规则上,定点数比浮点数简单,易于实现。因此,一般计算机中同时具有这两种表示方法,视具体情况进行选择应用。

 

3.我们可以把第二种方法改造一下,就能得到一种更好的方法。先把一个浮点数的小数点移到最后,用表示,R=10,然后再把M转换为二进制B,再用C做阶码,B做尾数用阶码尾数法表示。

例如:

314159用二进制表示为1001100101100101111

则它可表示为

10000101

10011001

0110010

11110000

阶码部分

尾数部分

用这种方法不仅可以精确表示浮点数的值,还可以充分的利用存储空间。

几种方法的比较:

1.  直接将浮点数转换为二进制方法无法精确表示。

2.  BCD码表示方便易懂,但不能充分利用空间。

3.  方法3既可以精确表示浮点数,又能很好的利用空间。

 

结束语:计算机的工作原理越来越无人问津了,人们都在忙着搞高级开发,好像底层的东西与自己无关。不管什么东西用别人的总是没有用自己的好,如果什么都用现成的,我们就难以真正做好。我对计算机的学习太少了,做的不好的地方望大家多多指教。

 

 

 

众所周知,计算机中的所有数据都是以二进制表示的,浮点数也不例外。然而浮点数的二进制表示法却不像定点数那么简单了。先澄清一个概念,浮点数并不一定等于小数,定点数也并不一定就是整数。所谓浮点数就是小数点在逻辑上是不固定的,而定点数只能表示小数点固定的数值,具用浮点数或定点数表示某哪一种数要看用户赋予了这个数的意义是什么。C++中的浮点数有6种,分别是:float:单精度,32位unsigned float:单精度无符号,32位double:双精度,64位unsigned double:双精度无符号,64位long double:高双精度,80位unsigned long double:高双精度无符号,80位(嚯,应该是C++中最长的内置类型了吧!)然而不同的编译器对它们的支持也略有不同,据我所知,很多编译器都没有按照IEEE规定的标准80位支持后两种浮点数的,大多数编译器将它们视为double,或许还有极个别的编译器将它们视为128位?!对于128位的long double我也仅是听说过,没有求证,哪位高人知道这一细节烦劳告知。下面我仅以float(带符号,单精度,32位)类型的浮点数说明C++中的浮点数是如何在内存中表示的。先讲一下基础知识,纯小数的二进制表示。(纯小数就是没有整数部分的小数,讲给小学没好好学的人)纯小数要想用二进制表示,必须先进行规格化,即化为 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。对于一个纯小数D,求n的公式如下:n = 1 + log2(D);// 纯小数求得的n必为负数再用 D / ( 2 ^ n ) 就可以得到规格化后的小数了。接下来就是十进制到二进制的转化问题,为了更好的理解,先来看一下10进制的纯小数是怎么表示的,假设有纯小数D,它小数点后的每一位数字按顺序形成一个集合:{k1, k2, k3, ... , kn}那么D又可以这样表示:D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )推广到二进制中,纯小数的表示法即为:D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )现在问题就是怎样求得b1, b2, b3,……,bn。算法描述起来比较复杂,还是用数字来说话吧。声明一下,1 / ( 2 ^ n )这个数比较特殊,我称之为位阶值。例如0.456,第1位,0.456小于位阶值0.5故为0;第2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进下一位;第3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;第4位,0.081大于0.0625,为1,并将0.081减去0.0625得0.0185进下一位;第5位0.0185小于0.03125……最后把计算得到的足够多的1和0按位顺序组合起来,就得到了一个比较精确的用二进制表示的纯小数了,同时精度问题也就由此产生,许多数都是无法在有限的n内完全精确的表示出来的,我们只能利用更大的n值来更精确的表示这个数,这就是为什么在许多领域,程序员都更喜欢用double而不是float。float的内存结构,我用一个带位域的结构体描述如下:struct MYFLOAT{bool bSign : 1;  // 符号,表示正负,1位char cExponent : 8;  // 指数,8位unsigned long ulMantissa : 23; // 尾数,23位};符号就不用多说了,1表示负,0表示正指数是以2为底的,范围是 -128 到 127,实际数据中的指数是原始指数加上127得到的,如果超过了127,则从-128开始计,其行为和X86架构的CPU处理加减法的溢出是一样的。比如:127 + 2 = -127;-127 - 2 = 127尾数都省去了第1位的1,所以在还原时要先在第一位加上1。它可能包含整数和纯小数两部分,也可能只包含其中一部分,视数字大小而定。对于带有整数部分的浮点数,其整数的表示法有两种,当整数大于十进制的16777215时使用的是科学计数法,如果小于或等于则直接采用一般的二进制表示法。科学计数法和小数的表示法是一样的。小数部分则是直接使用科学计数法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。拆开来看。0000000000000000000000000000000符号位指数位尾数位

 

原创粉丝点击