`

浮点数的表示和基本运算

阅读更多
浮点数的表示和基本运算
1 浮点数的表示

通常,我们可以用下面的格式来表示浮点数


S P M


其中S是符号位,P是阶码,M是尾数

对于IBM-PC而言,单精度浮点数是32位(即4字节)的,双精度浮点数是64位(即8字节)的。两者的S,P,M所占的位数以及表示方法由下表可知


S P M 表示公式 偏移量
1 8 23 (-1)S*2(P-127)*1.M 127
1 11 52 (-1)S*2(P-1023)*1.M 1023


以单精度浮点数为例,可以得到其二进制的表示格式如下


S(第31位) P(30位到23位) M(22位到0位)

其中S是符号位,只有0和1,分别表示正负;P是阶码,通常使用移码表示(移码和补码只有符号位相反,其余都一样。对于正数而言,原码,反码和补码都一样;对于负数而言,补码就是其绝对值的原码全部取反,然后加1.)

为了简单起见,本文都只讨论单精度浮点数,双精度浮点数也是用一样的方式存储和表示的。

2 浮点数的表示约定

单精度浮点数和双精度浮点数都是用IEEE754标准定义的,其中有一些特殊约定。

(1) 当P = 0, M = 0时,表示0。

(2) 当P = 255, M = 0时,表示无穷大,用符号位来确定是正无穷大还是负无穷大。

(3) 当P = 255, M != 0时,表示NaN(Not a Number,不是一个数)。

当我们使用.Net Framework的时候,我们通常会用到下面三个常量

Console.WriteLine(float.MaxValue); // 3.402823E+38
Console.WriteLine(float.MinValue);  //-3.402823E+38
Console.WriteLine(float.Epsilon);    //  1.401298E-45
//如果我们把它们转换成双精度类型,它们的值如下
Console.WriteLine(Convert.ToDouble(float.MaxValue)); // 3.40282346638529E+38
Console.WriteLine(Convert.ToDouble(float.MinValue));  //-3.40282346638529E+38
Console.WriteLine(Convert.ToDouble(float.Epsilon));    //  1.40129846432482E-45
那么这些值是如何求出来的呢?

根据上面的约定,我们可以知道阶码P的最大值是11111110(这个值是254,因为255用于特殊的约定,那么对于可以精确表示的数来说,254就是最大的阶码了)。尾数的最大值是11111111111111111111111。

那么这个最大值就是:0 11111110 11111111111111111111111。

也就是 2(254-127) * (1.11111111111111111111111)2 = 2127 * (1+1-2-23) = 3.40282346638529E+38

从上面的双精度表示可以看出,两者是一致的。最小的数自然就是-3.40282346638529E+38。

对于最接近于0的数,根据IEEE754的约定,为了扩大对0值附近数据的表示能力,取阶码P = -126,尾数 M = (0.00000000000000000000001)2 。此时该数的二进制表示为:0 00000000 00000000000000000000001

也就是2-126 * 2-23 = 2-149 = 1.40129846432482E-45。这个数字和上面的Epsilon是一致的。

如果我们要精确表示最接近于0的数字,它应该是 0 00000001 00000000000000000000000

也就是:2-126 * (1+0)  =  1.17549435082229E-38。

3 浮点数的精度问题

浮点数以有限的32bit长度来反映无限的实数集合,因此大多数情况下都是一个近似值。同时,对于浮点数的运算还同时伴有误差扩散现象。特定精度下看似相等的两个浮点数可能并不相等,因为它们的最小有效位数不同。

由于浮点数可能无法精确近似于十进制数,如果使用十进制数,则使用浮点数的数学或比较运算可能不会产生相同的结果。

如果涉及浮点数,值可能不往返。值的往返是指,某个运算将原始浮点数转换为另一种格式,而反向运算又将转换后的格式转换回浮点数,且最终浮点数与原始浮点数相等。由于一个或多个最低有效位可能在转换中丢失或更改,往返可能会失败。

4 将浮点数表示为二进制

4.1 无小数的浮点数转换成二进制表示

首先,我们用一个不带小数的浮点数来说明如何将一个浮点数转换成二进制表示。假设要转换的数据是45678.0f。

在处理这种不带小数的浮点数时,直接将整数部分转化为二进制表示:

1011001001101110.0,这时要加上一位默认的1(这是因为按照浮点数规格化的要求,尾数必须化成 1.M的格式),

那么可以表示成:11011001001101110.0。

然后将小数点向左移,一直移到离最高位只有1位,也就是 1.1011001001101110,一共移动了16位,我们知道,左移位表示乘法,右移位表示除法。所以原数就等于这样:1.1011001001101110 * ( 216 )。现在尾数和指数都出来了。因为最高位的1是根据标准加上去的,只是为了满足规格化的要求,这时候需要把这个1去掉。尾数的二进制就变成了:1011001001101110。

最后在尾数的后面补0,一直到补够23位,就是:10110010011011100000000。

再回来看指数,根据前面的定义,P-127=16,那么P = 143,表示成二进制就是:10001111。

45678.0f这个数是正的,所以符号位是0,那么我们按照前面讲的格式把它拼起来,就是:0 10001111 10110010011011100000000。

这就是45678.0f这个数的二进制表示,如果我们要得到16进制的表示,非常简单,我们只需要把这个二进制串4个一组,转换成16进制数就可以了。但是要注意的是x86架构的CPU都是Little Endian的(也就是低位字节在前,高位字节在后),所以在实际内存中该数字是按上面二进制串的倒序存储的。要知道CPU是不是little endian的也很容易。

BitConverter.IsLittleEndian;
4.2 含小数的浮点数表示为二进制

对于含小数的浮点数,会有精度的问题,下面举例说明。假设要转换的小数为123.456f。

对于这种带小数的就需要把整数部和小数部分开处理。对于整数部分的处理不再赘述,直接化成二进制为:100100011。小数部份的处理比较麻烦一些,我们知道,使用二进制表示只有0和1,那么对于小数就只能用下面的方式来表示:

a1*2-1+a2*2-2+a3*2-3+......+an*2-n

其中a1等数可以是0或者1,从理论上将,使用这种表示方法可以表示一个有限的小数。但是尾数只能有23位,那么就必然会带来精度的问题。

在很多情况下,我们只能近似地表示小数。来看0.456这个十进制纯小数,该如何表示成二进制呢?一般说来,我们可以通过乘以2的方法来表示。

首先,把这个数字乘以2,小于1,所以第一位为0,然后再乘以2,大于1,所以第二位为1,将这个数字减去1,再乘以2,这样循环下去,直到这个数字等于0为止。

在很多情况下,我们得到的二进制数字都大于23位,多于23位的就要舍去。舍入原则是0舍1入。通过这样的办法,我们可以得到二进制表示:1111011.01110100101111001。

现在开始向左移小数点,一共移了6位,这时候尾数为:1.11101101110100101111001,阶码为6加上127得131,二进制表示为:10000101,那么总的二进制表示为:

0  10000101  11101101110100101111001

表示成十六进制是:42  F6  E9  79

由于CPU是Little Endian的,所以在内存中表示为:79  E9  F6  42。

4.3 将纯小数表示成二进制

对于纯小数转化为二进制来说,必须先进行规格化。例如0.0456,我们需要把它规格化,变为1.xxxx * (2n )的形式,要求得纯小数X对应的n可用下面的公式:
n = int( 1 + log 2X )

0.0456我们可以表示为1.4592乘以以2为底的-5次方的幂,即1.4592 * ( 2-5 )。转化为这样形式后,再按照上面处理小数的方法处理,得到二进制表示

1. 01110101100011100010001

去掉第一个1,得到尾数

01110101100011100010001

阶码为:-5 + 127 = 122,二进制表示为

0  01111010  01110101100011100010001

最后转换成十六进制
11 C7 3A 3D

5 浮点数的数学运算

5.1 浮点数的加减法

设两个浮点数 X=Mx*2Ex ,Y=My*2Ey

实现X±Y要用如下5步完成:

(1)对阶操作:小阶向大阶看齐
(2)进行尾数加减运算
(3)规格化处理:尾数进行运算的结果必须变成规格化的浮点数,对于双符号位(就是使用00表示正数,11表示负数,01表示上溢出,10表示下溢出)的补码尾数来说,就必须是
001×××…×× 或110×××…××的形式
若不符合上述形式要进行左规或右规处理。
(4)舍入操作:在执行对阶或右规操作时常用“0”舍“1”入法将右移出去的尾数数值进行舍入,以确保精度。
(5)判结果的正确性:即检查阶码是否溢出

若阶码下溢(移码表示是00…0),要置结果为机器0;
若阶码上溢(超过了阶码表示的最大值)置溢出标志。

现在用一个具体的例子来说明上面的5个步骤

例题:假定X=0 .0110011*211,Y=0.1101101*2-10(此处的数均为二进制), 计算X+Y;

首先,我们要把这两个数变成2进制表示,对于浮点数来说,阶码通常用移码表示,而尾数通常用补码表示。

要注意的是-10的移码是00110
        [X]浮: 0        1 010  1100110
        [Y]浮: 0        0 110  1101101
                   符号位 阶码   尾数

(1)求阶差:│ΔE│=|1010-0110|=0100

(2)对阶:Y的阶码小,Y的尾数右移4位
        [Y]浮变为 0 1 010 0000110 1101暂时保存

(3)尾数相加,采用双符号位的补码运算
     00 1100110
   +00 0000110
     00 1101100

(4)规格化:满足规格化要求

(5)舍入处理,采用0舍1入法处理

故最终运算结果的浮点数格式为: 0 1 010 1101101

即X+Y=+0. 1101101*210

5.2 浮点数的乘除法

(1)阶码运算:阶码求和(乘法)或阶码求差(除法)
    即  [Ex+Ey]移= [Ex]移+ [Ey]补
          [Ex-Ey]移= [Ex]移+  [-Ey]补
(2)浮点数的尾数处理:浮点数中尾数乘除法运算结果要进行舍入处理

例题:X=0 .0110011*211,Y=0.1101101*2-10  求X*Y

解:[X]浮: 0 1 010 1100110
        [Y]浮: 0 0 110 1101101

(1)阶码相加
[Ex+Ey]移=[Ex]移+[Ey]补=1 010+1 110=1 000
1 000为移码表示的0

(2)原码尾数相乘的结果为:
0 10101101101110

(3)规格化处理:已满足规格化要求,不需左规,尾数不变,阶码不变。

(4)舍入处理:按舍入规则,加1进行修正

所以 X※Y= 0.1010111*20

分享到:
评论

相关推荐

    C#浮点数的表示和基本运算

    主要介绍了C#浮点数的表示和基本运算,需要的朋友可以参考下

    计算机组成原理第二章-运算方法与运算器

    计算机中的数据表示,熟悉包括定点数、浮点数、字符、十进制数的表示方法 ; 原码、补码、反码、移码等码制之间的关系以及各码制之间真值数的转换;...运算器的基本结构和设计方法,解已知芯片功能。

    计算机考研组成原理视频.zip

    2.3浮点数的表示与运算-运算 2.3浮点数的表示与运算 2.4算术逻辑单元ALU 3.1-2存储器的基本概念-存储器的层次结构 3.3半导体随机存储器 3.4主存储器与CPU的连接 3.5双口RAM多模块存储器 3.6高速缓冲存储器 3.7虚拟...

    高精度大数运算类

    该大数运算类是一个支持超高精度和超大数的基本运算类,最高精度能够达到一百亿位有效数字,最大能够表示10的2147483648次方,支持基础的四则运算和比较运算。该类的特点是使用指数形式表示数据,应此空间占用少,...

    Python基础语法:数据类型、进制转换、转义字符、字符编码、整数与浮点数运算规则、布尔型运算规则

    本人使用的python版本为:Python 3.7.4 Python中的基本数据类型 整数:和数学上的表示一样,如 1, 3, 100....整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的,而浮点数运算则可能会有四舍

    一个能够实现变量赋值和表达式计算的四则乘方括号运算计算器

    能够实现四则运算和乘方运算、赋值及报错的计算器 2018-12-4 -------------------------------------------------- 本程序的输入有三类:指令、赋值语句和计算式 这三类输入均允许在基本元素之间添加任意数目的...

    Java-关于基本数据类型中浮点数计算产生的精度问题

    在基本数据类型中,float和double都表示浮点型数据,而计算机计算采取的是对二进制的计算,所以会存在一定程度上的精度丢失问题。 BigDecimal类是一个大小数操作类,可以用来对超过16位有效位的数据进行精确的运算,...

    Python数字类型(整数类型、浮点数类型、复数类型)及基本操作

    浮点数是带有小数点及小数的数字,取值范围和小数精度都存在限制,但常规计算可忽略。浮点数间运算存在不确定尾数。可用round(x, d)对x四舍五入,d是小数截取位数。 可使用字母e或E作为幂的符号,以10为基数,格式:...

    Python基础案例教程-第2章-基本数据类型.pptx

    本章主要对Python的这三种基本的数据类型进行介绍,学习不同类型数据的基本运算,包括常用算术运算,关系运算,逻辑运算以及数据类型间的输出、转换方法等。 教学内容 Python基础案例教程-第2章-基本数据类型全文共...

    大数计算器大数计算器,采用迭代等算法我用它计算了上亿位的PI值

    添加新的基本运算函数,如:指数运算power、对数运算log、三角函数sin,cos,tan等 //注意:如果浮点数与TLargeFloat进行混合运算, 可能会产生误差(有效位数会受到浮点数影响); // 整数 或 为可表示整数的浮点数 ...

    组成原理课程设计报告

    部分内容如下所示: 计算机组成原理算法实现(二) 1 设计目的  本课程设计是在学完本课程教学大纲... 能够实现定点小数的机器数表示、定点小数的变形补码加减运算、定点小数的原码一位乘法运算和浮点数的加减运算。

    程序员二进制计算器 v1.36

    2-浮点数表示法 (1)小数点前后的省略表示 3.14 3. = 3.0 .14 = 0.14 (2)用科学计数法表示浮点数 3e2 = 300 3e+2 = 300 3e-2 = 0.03 3.e2 = 300 3.e+2 = 300 3.14e-2 = 0.0314 .14e+2 = 14 3-字符...

    计算机组成原理讲解.md

    计算机主要由五大部件组成:输入设备、输出设备、存储器、运算器和控制器。 输入设备:负责将人类可识别的信息转换为计算机可处理的电信号,如键盘、鼠标、扫描仪等。 输出设备:将计算机处理后的结果转换为人类可...

    Word版的Maple 手册

    1.2.1 无理数和浮点数 22 1.2.2 代数数(Algebraic Numbers) 23 1.2.3 复数运算 24 1.3 Maple中的变量和常量 25 1.3.1 赋值 25 1.3.2 变量名 27 1.3.3 基本数据类型 29 1.3.4 Maple中的常数 31 1.4 函数和表达式 32...

    中级软件设计师 (1)-看各大佬视频整理

    数据的表示-浮点数运算 计算机结构 计算机体系结构分类-Flynn CISC与RISC 流水线 流水线---计算 流水线---流水线吞吐率计算 流水线---加速比 流水线---效率计算 层次化存储结构 Cache-概念 主存编址计算 磁盘结构与...

    Python的基本语法、常用库以及其在各个领域的应用

    NumPy:用于处理大型多维数组和矩阵运算的库,是数据分析、机器学习等领域的基石。 Pandas:提供数据结构和数据分析工具的库,支持数据清洗、转换、聚合等操作,是数据处理领域的利器。 Matplotlib:用于绘制各种...

    基础二进制知识.pptx

    二进制是一种计数系统,...二进制在计算机系统中被广泛使用,因为电子器件可以简单地表示两个状态(开和关),并且容易进行逻辑运算。计算机将数据转换为二进制形式进行存储和处理,包括整数、浮点数、字符和指令等。

    华中师范大学数学系考研复试真题

    6.基本概念:溢出及判断方法、数的补码表示及求补、对阶、规格化同步控制和异步控制(含义、应用场合)、组合逻辑控制与微程序控制(基本思想、优缺点、应用场合)、中断方式与DMA方式(定义、应用场合)、程序状态...

Global site tag (gtag.js) - Google Analytics