浮点数在计算机内存中的存储格式

浮点数在计算机内存中的存储格式
浮点数在计算机内存中的存储格式

浮点数在计算机内存中的存储格式

对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用 32bit,double数据占用 64bit,我们在声明一个变量float f = 2.25f的时候,是如何分配内存的呢?其实不论是float类型还是double类型,在计算机内存中的存储方式都是遵从IEEE的规范的,float 遵从的是IEEE

R32.24 ,而double 遵从的是R64.53。

无论是单精度还是双精度,在内存存储中都分为3个部分:

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

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

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

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

而双精度的存储方式为:

R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十

进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*。而我

们傻蛋计算机根本不认识十进制的数据,它只认识0和1,所以在计算机内存中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,120.5用二进制表示为:1110110.1。用二进制的科学计数法

表示1000.01可以表示为1.00001*,1110110.1可以表示为 1.1101101*,任何一个数的科学计数法表示都为 1.xxx*, 尾数部分就可以表示为xxxx,第一

位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了 24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127。

下面就看看8.25和120.5在内存中真正的存储方式:

首先看下8.25,用二进制的科学计数法表示为:1.0001*

按照上面的存储方式,符号位为0,表示为正;指数位为3+127=130,位数部分为 1.00001,故8.25的存储方式如下:

0xbffff380: 01000001000001000000000000000000

分解如下:0--10000010--00001000000000000000000

符号位为0,指数部分为10000010,位数部分为 00001000000000000000000

同理,120.5在内存中的存储格式如下:

0xbffff384: 01000010111100010000000000000000

分解如下:0--10000101--11100010000000000000000

那么如果给出内存中一段数据,并且告诉你是单精度存储的话,你如何知道该数据的十进制数值呢?其实就是对上面的反推过程,比如给出如下内存数据:

01000001001000100000000000000000

第一步:符号位为0,表示是正数;

第二步:指数位为10000010,换算成十进制为130,所以指数为130-127=3;

第三步:尾数位为01000100000000000000000,换算成十进制为 (1+1/4+1/64);

所以相应的十进制数值为:2^3*(1+1/4+1/64)=8+2+1/8=10.125

再看一个例子,观察其输出:

02 {

03 float f1 = 2.2;

04 float f2 = 2.25;

05

06 double d1 = (double)f1;

07 double d2 = (double)f2;

08

09 printf ("d1 = %.13f, d2 = %.13f\n", d1, d2);

10

11 return 0;

12 }

[doyle@phuang algorithm]$ ./a.out

d1 = 2.2000000476837, d2 = 2.2500000000000

可能输出的结果让大家疑惑不解,单精度的2.2转换为双精度后,精确到小数点后13位后变为了2.2000000476837,而单精度的2.25 转换为双精度后,变为了2.2500000000000,为何2.2在转换后的数值更改了而2.25却没有更改呢?很奇怪吧?其实通过上面关于两种存储结果的介绍,我们已经大概能找到答案。首先我们看看2.25的单精度存储方式:0 10000000 00100000000000000000000,而2.25的双精度表示为:0 100 0000 0001 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000,这样2.25在进行强制转换的时候,数值是不会变的。我们再看看2.2的单精度和双精度内存表示,2.2用科学计数法表示应该为:将十进制的小数转换为二进制的小数的方法为将小数*2,取整数部分,所以0.282=0.4,所以二进制小数第一位为0.4的整数部分0,0.4×2=0.8,第二位为 0,0.8*2=1.6,第三位为1,0.6×2 = 1.2,第四位为1,0.2*2=0.4,第五位为0,这样永远也不可能乘到=1.0,得到的二进制是一个无限循环的排列00110011001100110011... ,对于单精度数据来说,尾数只能表示24bit的精度,所以2.2的float存储为:0 10000000 00011001100110011001101

但是这样存储方式,换算成十进制的值,却不会是2.2的,应为十进制在转换为二进制的时候可能会不准确,如2.2,而double类型的数据也存在同样的问题,所以在浮点数表示中会产生些许的误差,在单精度转换为双精度的时候,也会存在误差的问题,对于能够用二进制表示的十进制数据,如 2.25,这个误差就会不存在,所以会出现上面比较奇怪的输出结果。

总结:浮点数在内存中的存储表示是以2的负数次方来模拟和逼近的,如果浮点数的小数部分可以用二进制完美地表示,则浮点数转化为二进制存储的时候不会存在精度丢失,否则内存中的这种表示浮点数的方法将会导致浮点数的精度丢失,如上面的2.2;

C语言float类型浮点数的存储方法

C语言float类型浮点数的存储方法 #include int main(int argc, char *argv[]) { float p = 5.1f; int f = (int)(p*100); printf("%d", f); getch(); return 0; } 我想要输出 510,可是机器居然输出509。 我试着把5.1改成5.5,一切正常。 IEEE规定的浮点数的机器表示: 32位机器的 float 是4字节的,共32位。 第1位是符号位,接着8位指数位,接着23位基数位。 以5.1为例。 5 = 101 (2进制) 0.1 = 0.0 0011 0011 0011 0011 0011 0011 .....(无限循环) 所以 5.1 = 101.0 0011 0011 0011 0011 0011 0011 0011 0011 ... 5.1= 1.010 0011 0011 0011 0011 0011 0011 0011 0011 0011... * 2^2 因为第一位总是为1,如果是0,就移动小数点直到是非0的,所以第一位的1丢弃。得到 010 0011 0011 0011 0011 0011 0011 0011 0011.... 取23位得到 0100 0110 0110 0110 0110 011 接着看指数部分 指数是2, 根据规定,指数统一+127再转换为无符号8位2进制数, 2+127=129 (1000 0001) 存储的时候指数部分存储在基数之前,这样就有31位了, 因为5.1是正的,所以符号为是0,存储在指数部分之前 这样就得到 0100 0000 1010 0011 0011 0011 0011 0011 我们来看一下机器上是否真的如此 #include #include int main(int argc, char *argv[])

浮点数存储

浮点数存储.txt世上最珍贵的不是永远得不到或已经得到的,而是你已经得到并且随时都有可能失去的东西!爱情是灯,友情是影子。灯灭时,你会发现周围都是影子。朋友,是在最后可以给你力量的人。浮点数: 浮点型变量在计算机内存中占用4字节(Byte),即32-bit。遵循IEEE-754格式标准。一个浮点数由2部分组成:底数m 和指数e。 ±mantissa × 2exponent (注意,公式中的mantissa 和 exponent使用二进制表示) 底数部分使用2进制数来表示此浮点数的实际值。 指数部分占用8-bit的二进制数,可表示数值范围为0-255。 指数应可正可负,所以IEEE规定,此处算出的次方须减去127才是真正的指数。所以float 的指数可从 -126到128 底数部分实际是占用24-bit的一个值,由于其最高位始终为 1 ,所以最高位省去不存储,在存储中只有23-bit。 到目前为止,底数部分 23位加上指数部分 8位使用了31位。那么前面说过,float是占用4个字节即32-bit,那么还有一位是干嘛用的呢?还有一位,其实就是4字节中的最高位,用来指示浮点数的正负,当最高位是1时,为负数,最高位是0时,为正数。 浮点数据就是按下表的格式存储在4个字节中: Address+0 Address+1 Address+2 Address+3 Contents SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM S: 表示浮点数正负,1为负数,0为正数 E: 指数加上127后的值的二进制数 M: 24-bit的底数(只存储23-bit) 注意:这里有个特例,浮点数为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。当然,这个特例也不用认为去干扰,编译器会自动去识别。 举例1:计算机存储中的二进制数如何转换成实际浮点数 通过上面的格式,我们下面举例看下-12.5在计算机中存储的具体数据: Address+0 Address+1 Address+2 Address+3 Contents 0xC1 0x48 0x00 0x00 接下来我们验证下上面的数据表示的到底是不是-12.5,从而也看下它的转换过程。 由于浮点数不是以直接格式存储,他有几部分组成,所以要转换浮点数,首先要把各部分的值分离出来。 Address+0 Address+1 Address+2 Address+3 格式 SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM

浮点数规格化和教案

第一节 X=(-1)S×(1.M)×2E-127e=E-127 X=(-1)S×(1.M)×2E-1023 e=E-1023 我承认以前对这俩公式避之不及不予深究努力自己说服自己而未能得逞,部分原因是跟“移码与真值的关系”扯上关系,这“移码与真值的关系”想搞清先得把引入移码的充分理由给我个说法,不幸玩过头正事误了。上回说了“补码省心移码悦目”能算是今时不同往日了吧,现在轮到对IEEE754浮点数规格化表示法杀无赦去死吧。 首先,“IEEE规格化形式”是对“传统规格化形式”进一步严格要求来的。 IEEE规格化形式唯一,而浮点数记法多种多样。 (1.75)10=1.11×20 (IEEE规格化表示)=0.111×21 (传统规格化表示) =0.0111×22=0.00111×23 其次,既然IEEE想到对“传统规格化形式”进一步修订当然有目的,你以为作无用功呐,关键目的是什么? 规格化的目的同理。修改阶码同时左右移小数点使尾数域最高有效位固定为1,尾数就以ta所可能变化成的最大形式出现,即使遭遇类似截断的操作仍可保持尽可能高的精度。 有类错误我这种大秀逗极善于犯!就是不理会左右关系不经过大脑直接作问题少女状问很白的问题:“‘移码和真值的关系’是E=27(或210)+X,那X=E-27(或210),在怎么着里面数该是128(或1024),咋是127(或1023)?” 当E=M=全0 E(移码)=全0,对应真值-128 M(补码)=全0,对应真值0 E=M=全0,真值X=0-128=0 结合符号位S 为0或1分正零和负零 当E=全1,M=全0 E(移码)=全1,对应真值+127 M(补码)=全0,对应真值0 E=全1,M=全0,真值X=0127=∞ 结合符号位S 为0或1分+∞和-∞ 要除去表示零和无穷大这2种特殊情况 指数偏移值不选128(10000000),而选127(01111111) 对IEEE32位规格化浮点数 8位移码(隐含1位符号位)原本表示范围是-128 →+127 (除去全1(+127)全0(-128)剩下-127 →+126 ???) 实际可用指数值(即阶码真值)e范围是-126→+127 加上偏移值后,阶码E的范围变为1→254 以10的幂表示,绝对值的范围是10-38→1038 假设由S,E,M三个域组成的一个32位二进制字所表示的非零规格化浮点数x,真值表示为:x=(-1)s×(1.M)×2E-128 它所表示的规格化的最大正数、最小正数、最大负数、最小负数是多少? 第二节 1、什么是IEEE754标准 用来规范化浮点数,其格式是

数据在计算机中的表示

选择题 1.信息处理进入了计算机世界,实质上是进入了世界。 A、模拟数字 B、十进制数 C、二进制数 D、抽象数字 答案:C 2.计算机中使用二进制,下面叙述中不正确的是。 A、是因为计算机只能识别0和1 B、物理上容易实现,可靠性强 C、运算,通用性强 D、计算机在二进制数的0、1数码与逻辑量“真”和“假”的0与1吻合,便于表示和进行逻辑运算 答案:A 3.十进制数92转换为二进制数和十六进制数分别是。 A、01011100和5C B、01101100和61 C、和5D D、01011000和4F 答案:A 4.人们通常用十六进制而不用二进制书写计算机中的数,是因为。 A、十六进制的书写比二进制方便 B、十六进制的运算规则比二进制简单 C、十六进制数表达的范围比二进制大 D、计算机内部采用的是十六进制 答案:A 5.浮点数之所以能表示很大或很小的数,是因为使用了。 A、较多的字节 B、较长的尾数 C、阶码

D、符号位 答案:C 6.在科学计算时,经常会遇到“溢出”,这是指。 A、数值超出了内存容量 B、数值超出了机器的位所能表示的范围 C、数值超出了变量的表示范围 D、计算机出故障了 答案:B 7.下列有关二进制的说法中,是错误的。 A、二进制数只有0和1两个数码 B、二进制数只由两位数组成 C、二进制数各位上的权分别为1,2,4,…… D、二进制运算逢二进一 答案:B 8.下列关于字符之间大小关系的说法中,正确的是。 A、空格符>b>B B、空格符>B>b C、b>B>空格符 D、B>b>空格符 答案:C 9.目前在微机上最常用的字符编码是。 A、汉字字型码 B、ASCII码 C、8421码 D、EBCDIC码 答案:B 10.计算机多媒体技术是以计算机为工具,接受、处理和显示由等表示的信息技术。 A、中文、英文、日文 B、图像、动画、声音、文字和影视

第三章 数据在计算机中的表示知识及答案

第三章数据在计算机中的表示 一、选择题 1.在下面关于字符之间大小关系的说法中,正确的是_____________。 A. 空格符>b>B B.空格符>B>b C.b>B>空格符 D.B>b>空格符 2.汉字系统中的汉字字库里存放的是汉字的_____________。 A. 机内码 B.输入码C.字形码 D.国标码 3.在汉字库中查找汉字时,输入的是汉字的机内码,输出的是汉字的()。 A. 交换码 B. 信息码 C. 外码 D. 字形码 4.对补码的叙述,_____________不正确。 A.负数的补码是该数的反码最右加1 B.负数的补码是该数的原码最右加1 C.正数的补码就是该数的原码 D.正数的补码就是该数的反码 5.十进制数92转换为二进制数和十六进制数分别是_____________。 A.01011100和5C B.01101100和61 C.10101011和5D D.01011000和4F 6.人们通常用十六进制而不用二进制书写计算机中的数,是因为_____________。 A. 十六进制的书写比二进制方便 B.十六进制的运算规则比二进制简单 C.十六进制数表达的范围比二进制大 D.计算机内部采用的是十六进制 7.二进制数 10011010 转换为十进制数是()。 A. 153 B. 156 C. 155 D. 154 8.在科学计算时,经常会遇到“溢出”,这是指_____________。 A.数值超出了内存容量 B.数值超出了机器的位所表示的范围 C.数值超出了变量的表示范围 D.计算机出故障了 9.有关二进制的论述,下面_____________是错误的。 A. 二进制数只有0和l两个数码 B.二进制数只有两位数组成 C.二进制数各位上的权分别为2i(i为整数) D.二进制运算逢二进一 10.目前在微型计算机上最常用的字符编码是_____________。 A.汉字字型码 B.ASCII码 C.8421码 D.EBCDIC码 11.在计算机内,多媒体数据最终是以_____________形式存在的。 A.二进制代码 B.特殊的压缩码 C.模拟数据 D.图形 12.在不同进制的4个数中,最大的一个数是_____________。 A.01010011 B B.67 O C.5F H D.78 D 13.在计算机中存储一个汉字信息需要()字节存储空间。 A. 1 B. 2 C. 3 D. 4 14.计算机中的机器数有3种表示方法,下列_____________不属于这3种表示方式。

数据在计算机中的表示

数据在计算机中的表示 数据是计算机处理的对象。这里的"数据"含义非常广泛,包括数值、文字、图形、图像、视频等各种数据形式。计算机内部一律采用二进制表示数据。 为什么要用二进制? 二进制并不符合人们的习惯,但是计算机内部仍采用二进制表示信息,其主要原因。有以下四点: 1.电路简单计算机是由逻辑电路组成,逻辑电路通常只有两个状态。例如,开关的接通与断开,晶体管的饱和与截止,电压电平的高与低等。这两种状态正好用来表示二进制数的两个数码0和l。 2.工作可靠 两个状态代表的两个数码在数字传输和处理中不容易出错,因而电路更加可靠。3.简化运算 二进制运算法则简单。例如,求积运算法则只有3个。而十进制的运算法则(九九乘法表)对人来说虽习以为常,但是让机器去实现就是另一回事了。 4.逻辑性强 计算机的工作是建立在逻辑运算基础上的,逻辑代数是逻辑运算的理论依据。有两个数码,正好代表逻辑代数中的"真"与"假"。 数据单位 二进制只有两个数码0和l,任何形式数据都要靠0和1来表示。为了能有效地表示和存储不同形式的数据,人们使用了下列不同的数据单位: 1.位(bit)位,音译为"比特",是计算机存储数据、表示数据的最小单位。一个bit只能表示一个开关量,例如l代表"开关闭合",0代表"开关断开"。 2.字节(byte)字节来自英文Byte,简记为B,音译为"拜特"。规定l个字节等于8个位,即lByte=8 bit。字节是个重要的数据单位,表现在:.计算机存储器是以字节为单位组织的,每个字节都有一个地址码(就像门牌号码一样),通过地址码可以找到这个字节,进而能存取其中的数据;.字节是计算机处理数据的基本单位,即以宇节为单位解释信息。.计算机存储器容量大小是以宇节数来度量的,经常使用的单位有B、KB、MB、GB。1KB=2(10次

2.浮点数的存储原理

问题:long和float类型都是四个字节,为什么存储数值的范围相差极大? 原因:因为两者的存储原理时不同的。 浮点数的存储原理 作者: jillzhang 联系方式:jillzhang@https://www.360docs.net/doc/2014632477.html, 本文为原创,转载请保留出处以及作者,谢谢 C语言和C#语言中,对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用32bit,double数据占用64bit,我们在声明一个变量float f= 2.25f的时候,是如何分配内存的呢?如果胡乱分配,那世界岂不是乱套了么,其实不论是float还是double在存储方式上都是遵从IEEE的规范的,float遵从的是IEEE R32.24 ,而double 遵从的是R64.53。 无论是单精度还是双精度在存储中都分为三个部分: 1.符号位(Sign) : 0代表正,1代表为负 2.指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储 3.尾数部分(Mantissa):尾数部分 其中float的存储方式如下图所示: 而双精度的存储方式为:

R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*,这些小学的知识就不用多说了吧。而我们傻蛋计算机根本不认识十进制的数据,他只认识0,1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,我靠,不会连这都不会转换吧?那我估计要没辙了。120.5用二进制表示为:1110110.1用二进制的科学计数法表示1000.01可以表示为1.0001* ,1110110.1可以表示为1.1101101*,任何一个数都的科学计数法表示都为1.xxx*,尾数部分就可以表示为xxxx,第一位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127,下面就看看8.25和120.5在内存中真正的存储方式。 首先看下8.25,用二进制的科学计数法表示为:1.0001* 按照上面的存储方式,符号位为:0,表示为正,指数位为:3+127=130 ,位数部分为,故8.25的存储方式如下图所示: 而单精度浮点数120.5的存储方式如下图所示:

数值数据在计算机中的表示方法

数值数据在计算机中的表示方式 日常生活中,经常采用的进位制很多,比如,一打等于十二个(十二进制)、一小时等于六十分(六十进制)、一米等于十分米(十进制)等等。其中十进制是最常用的,它的特点是有10个数码:0~9,进位关系是“逢十进一”。而在计算机中数的表示是采用二进制。为了书写和读数方便还用到八进制和十六进制。如表1.1。 1. 计算机中的二进制数 二进制是逢二进一,所有的数都用两个数字符号0或1表示。二进制的每一位只能表示0或1。例如:(1)10 = (001)2 ,(2)10 = (010)2 ,(3)10 = (011)2 。 即十进制数1,2,3用二进制表示分别为:001,010,011等等。 计算机采用二进制的原因在于: (1)0和1两个数可分别用电器中两种状态来表示,很容易用电器元件来实现。如开关的接通为1,断开为0;高电平为1,低电平为0等,而要用电路的状态来表示我们已熟悉的十进制等,就要制作出具有十个稳定状态的元件,这是相当困难的; (2)计算机只能直接识别二进制数符0和1,而且二进制的运算公式很简单,计算机很容易实现,逻辑判断也容易。 (3)可以节省设备。 2. 八进制 二进制的缺点是表示一个数需要的位数多,书写数据和指令不方便。通常,为方便起见,将二进制数从低向高每三位或四位组成一组。例如:有一个二进制(100100001100)2,若每三位一组,即:(100,100,001,100)2可表示成八进制数(4414)8,如此表示使得每组的值大小是从0(000)~7(111),且数值逢八进一,即为八进制。 3. 十六进制 若每四位为一组,即:(1001,0000,1100)2,每组的值大小是从0(0000)~15(1111),且逢16进一,即为十六进制。用A,B,C,D,E,F分别代表10到15的6个数,则上面的二进制数可以表示成十进制数(90C)16。 4. 有关的概念 位(Bit)指一位二进制代码,它只具有“0”和“1”两个状态。 字节(Byte)8位二进制代码为一个字节,它是衡量信息数量或存储设备容量的单位。CPU向存储器存取信息时,是以字(或字节)为单位的。 字(Word)字由字节构成,一般为字节的整数倍。也是表示存储容量的单位。 字长是指参与一次运算的数的位数,它与指令长度有着对应关系。字长的大小还是衡

有关浮点数在内存中的存储

有关浮点数在内存中的存储 最近想看一下C中float和double型数据在内存中是如何表示的,找到了如下一些东东,与大家分享一下 c语言中FLOAT 是如何表示的?尾数,阶码是如何在32位上安排的,即哪几位是尾数,哪几位是阶码,那一位是符号位。听说与CPU有关,是真的吗? 在C++里,实数(float)是用四个字节即三十二位二进制位来存储的。其中有1位符号位,8位指数位和23位有效数字位。实际上有效数字位是24位,因为第一位有效数字总是“1”,不必存储。 有效数字位是一个二进制纯小数。8位指数位中第一位是符号位,这符号位和一般的符号位不同,它用“1”代表正,用”0“代表负。整个实数的符号位用“1”代表负,“0”代表正。 在这存储实数的四个字节中,将最高地址字节的最高位编号为31,最低地址字节的最低位编号为0,则实数各个部分在这32个二进制位中的分布是这样的:31位是实数符号位,30位是指数符号位,29---23是指数位,22---0位是有效数字位。注意第一位有效数字是不出现在内存中的,它总是“1”。 将一个实数转化为C++实数存储格式的步骤为: (1)先将这个实数的绝对值化为二进制格式,注意实数的整数部分和小数部分化为二进制的方法是不同的。 (2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边。 (3)从小数点右边第一位开始数出二十三位数字放入第22到第0位。 (4)如果实数是正的,则在第31位放入“0”,否则放入“1”。 (5)如果n 是左移得到的,说明指数是正的,第30位放入“1”。如果n是右移得到的或n=0,则第30位放入“0”。 (6)如果n是左移得到的,则将n减去一然后化为二进制,并在左边加“0”补足七位,放入第29到第23位。如果n是右移得到的或n=0,则将n化为二进制后在左边加“0”补足七位,再各位求反,再放入第29到第23位。 将一个计算机里存储的实数格式转化为通常的十进制的格式的方法如下: (1)将第22位到第0位的二进制数写出来,在最左边补一位“1”,得到二十四位有效数字。将小数点点在最左边那个“1”的右边。 (2)取出第29到第23位所表示的值n。当30位是“0”时将n各位求反。当30位是“1”时将n增1。 (3)将小数点左移n位(当30位是“0”时)或右移n位(当30位是“1”时),得到一个二进制表示的实数。 (4)将这个二进制实数化为十进制,并根据第31位是“0”还是“1”加上正号或负号即可。

浮点数的表示和基本运算

浮点数的表示和基本运算 1 浮点数的表示 通常,我们可以用下面的格式来表示浮点数 S P M 其中S是符号位,P是阶码,M是尾数 对于IBM-PC而言,单精度浮点数是32位(即4字节)的,双精度浮点数是64位(即8字节)的。两者的S,P,M所占的位数以及表示方法由下表可知 S P M表示公式偏移量 1823(-1)S*2(P-127)*1.M127 11152(-1)S*2(P-1023)*1.M1023 以单精度浮点数为例,可以得到其二进制的表示格式如下 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长度来反映无限的实数集合,因此大多数情况下都是一个近似值。同时,对于浮点数的运算还同时伴有误差扩散现象。特定精度下看似

浮点数在内存中的存储方式

浮点数在内存中的存储方式 任何数据在内存中都是以二进制的形式存储的,例如一个short型数据1156,其二进制表示形式为00000100 10000100。则在Intel CPU架构的系统中,存放方式 为10000100(低地址单元) 00000100(高地址单元),因为Intel CPU的架构是小端模式。但是对于浮点数在内存是如何存储的?目前所有的C/C++编译器都是采用IEEE所制定的标准浮点格式,即二进制科学表示法。 在二进制科学表示法中,S=M*2^N 主要由三部分构成:符号位+阶码(N)+尾数(M)。对于float型数据,其二进制有32位,其中符号位1位,阶码8位,尾数23位;对于double型数据,其二进制为64位,符号位1位,阶码11位,尾数52位。 31 30-23 22-0 float 符号位阶码尾数 63 62-52 51-0 double 符号位阶码尾数 符号位:0表示正,1表示负 阶码:这里阶码采用移码表示,对于float型数据其规定偏置量为127,阶码有正有负,对于8位二进制,则其表示范围为-128-127,double型规定为1023,其表示范围为 -1024-1023。比如对于float型数据,若阶码的真实值为2,则加上127后为129,其阶码表示形式为10000010 尾数:有效数字位,即部分二进制位(小数点后面的二进制位),因为规定M的整数部分恒为1,所以这个1就不进行存储了。

下面举例说明: float型数据125.5转换为标准浮点格式 125二进制表示形式为1111101,小数部分表示为二进制为1,则125.5二进制表示为1111101.1,由于规定尾数的整数部分恒为1,则表示为1.1111011*2^6,阶码为6,加上127为133,则表示为10000101,而对于尾数将整数部分1去掉,为1111011,在其后面补0使其位数达到23位,则为11110110000000000000000 则其二进制表示形式为 0 10000101 11110110000000000000000,则在内存中存放方式为: 00000000 低地址 00000000 11111011 01000010 高地址 而反过来若要根据二进制形式求算浮点数如0 10000101 11110110000000000000000 由于符号为为0,则为正数。阶码为133-127=6,尾数为11110110000000000000000,则其真实尾数为1.1111011。所以其大小为 1.1111011*2^6,将小数点右移6位,得到1111101.1,而1111101的十进制为125,0.1的十进制为1*2^(-1)=0.5,所以其大小为125.5。 同理若将float型数据0.5转换为二进制形式

单双精度浮点数的IEEE标准格式

单双精度浮点数的IEEE标准格式 目前大多数高级语言(包括C)都按照IEEE-754标准来规定浮点数的存储格式,IEEE754规定,单精度浮点数用4字节存储,双精度浮点数用 8字节存储,分为三个部分:符号位、阶和尾数。阶即指数,尾数即有效小数位数。单精度格式阶占8位,尾数占24位,符号位1位,双精度则为11为阶,53 位尾数和1位符号位,如下图所示: 31 30 23 22 0 63 62 52 51 0 细心的人会发现,单双精度各部分所占字节数量比实际存储格式都了一位,的确是这样,事实是,尾数部分包括了一位隐藏位,允许只存储23位就可以表示24位尾数,默认的1位是规格化浮点数的第一位,当规格化一个浮点数时,总是调整它使其值大于等于1而小于2,亦即个位总是为1。例如1100B,对其规格化的结果为1.1乘以2的三次方,但个位1并不存储在23位尾数部分内,这个1是默认位。 阶以移码的形式存储。对于单精度浮点数,偏移量为127(7FH),而双精度的偏移量为1023(3FFH)。存储浮点数的阶码之前,偏移量要先加到阶码上。前面例子中,阶为2的三次方,在单精度浮点数中,移码后的结果为127+3即130(82H),双精度为1026(402H)。 浮点数有两个例外。数0.0存储为全零。无限大数的阶码存储为全1,尾数部分全零。符号位指示正无穷或者负无穷。 下面举几个例子:

所有字节在内存中的排列顺序,intel的cpu按little endian顺序,motorola 的cpu按big endian顺序排列。

IEEE754标准的一个规格化 32位浮点数x的真值可表示为 x=(-1)^S*(1.M)*2^(E-127)e=E-127 31 30 23 0 |S | E |M | [例1]若浮点数x的754标准存储格式为(41360000)16,求其浮点数的十进制数值。 解:将16进制展开后,可得二进制数格式为 0 100,0001,0 011,0110,0000,0000,0000,0000 S E M 指数e=100,0001,0-01111111=00000011=(3)10 包含隐藏位1的尾数1.M=1.011,0110,0000,0000,0000,0000 于是有x=(-1)^0*(1.M)*2^(E-127) =+(1.011011)2*2^3 =(11.375)10 [例2]将数(20.59375)10转化为754标准的32位浮点数的二进制存储格式。解:首先分别将整数部分和小数部分转换成二进制 (20.59375)10=+(10100.10011)2 然后移动小数点使其在1,2位之间 10100.10011=1.010010011*2^4 e=4 于是得到:S=0,E=e+127=131,M=010010011 最后得到32位浮点数的二进制存储格式为 0 100,0001,1 010,0100,1100,0000,0000,0000 =(41A4C000)16 从存储结构和算法上来讲,double和float是一样的,不一样的地方仅仅是float是32位的,double是64位的,所以double能存储更高的精度。 任何数据在内存中都是以二进制(0或1)顺序存储的,每一个1或0被称为1位,而在 x86CPU上一个字节是8位。比如一个16位(2字节)的 short int型变量的值是1000,那么它的二进制表达就是:00000011 11101000。由于Intel CPU的架构原因,它是按字节倒序存储的,那么就因该是这样:11101000 00000011,这就是定点数1000在内存中的结构。 目前C/C++编译器标准都遵照IEEE制定的浮点数表示法来进行float,double运算。这种结构是一种科学计数法,用符号、指数和尾数来表示,底数定为2——即把一个浮点数表示为尾数乘以2的指数次方再添上符号。下面是具体的规格: ````````符号位阶码尾数长度 float 1 8 23 32 double 1 11 52 64

浮点数在计算机内存中的存储格式

浮点数在计算机内存中的存储格式 对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,float数据占用 32bit,double数据占用 64bit,我们在声明一个变量float f = 2.25f的时候,是如何分配内存的呢?其实不论是float类型还是double类型,在计算机内存中的存储方式都是遵从IEEE的规范的,float 遵从的是IEEE R32.24 ,而double 遵从的是R64.53。 无论是单精度还是双精度,在内存存储中都分为3个部分: 1) 符号位(Sign):0代表正,1代表为负; 2) 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储; 3) 尾数部分(Mantissa):尾数部分; 其中float的存储方式如下图所示: 而双精度的存储方式为: R32.24和R64.53的存储方式都是用科学计数法来存储数据的,比如8.25用十 进制的科学计数法表示就为:8.25*,而120.5可以表示为:1.205*。而我 们傻蛋计算机根本不认识十进制的数据,它只认识0和1,所以在计算机内存中,首先要将上面的数更改为二进制的科学计数法表示,8.25用二进制表示可表示为1000.01,120.5用二进制表示为:1110110.1。用二进制的科学计数法 表示1000.01可以表示为1.00001*,1110110.1可以表示为 1.1101101*,任何一个数的科学计数法表示都为 1.xxx*, 尾数部分就可以表示为xxxx,第一

位都是1嘛,干嘛还要表示呀?可以将小数点前面的1省略,所以23bit的尾数部分,可以表示的精度却变成了 24bit,道理就是在这里,那24bit能精确到小数点后几位呢,我们知道9的二进制表示为1001,所以4bit能精确十进制中的1位小数点,24bit就能使float能精确到小数点后6位,而对于指数部分,因为指数可正可负,8位的指数位能表示的指数范围就应该为:-127-128了,所以指数部分的存储采用移位存储,存储的数据为元数据+127。 下面就看看8.25和120.5在内存中真正的存储方式: 首先看下8.25,用二进制的科学计数法表示为:1.0001* 按照上面的存储方式,符号位为0,表示为正;指数位为3+127=130,位数部分为 1.00001,故8.25的存储方式如下: 0xbffff380: 01000001000001000000000000000000 分解如下:0--10000010--00001000000000000000000 符号位为0,指数部分为10000010,位数部分为 00001000000000000000000 同理,120.5在内存中的存储格式如下: 0xbffff384: 01000010111100010000000000000000 分解如下:0--10000101--11100010000000000000000 那么如果给出内存中一段数据,并且告诉你是单精度存储的话,你如何知道该数据的十进制数值呢?其实就是对上面的反推过程,比如给出如下内存数据: 01000001001000100000000000000000 第一步:符号位为0,表示是正数; 第二步:指数位为10000010,换算成十进制为130,所以指数为130-127=3; 第三步:尾数位为01000100000000000000000,换算成十进制为 (1+1/4+1/64); 所以相应的十进制数值为:2^3*(1+1/4+1/64)=8+2+1/8=10.125 再看一个例子,观察其输出: 02 { 03 float f1 = 2.2; 04 float f2 = 2.25;

浮点数1

浮点数在计算机中用以近似表示任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到,这种表示方法类似于基数为10的科学记数法。 浮点计算是指浮点数参与的运算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。 一个浮点数a由两个数m和e来表示:a = m × be。在任意一个这样的系统中,我们选择一个基数b(记数系统的基)和精度p(即使用多少位来存储)。m(即尾数)是形如±d.ddd...ddd的p位数(每一位是一个介于0到b-1之间的整数,包括0和b-1)。如果m的第一位是非0整数,m称作规格化的。有一些描述使用一个单独的符号位(s 代表+或者-)来表示正负,这样m必须是正的。e是指数。 这种设计可以在某个固定长度的存储空间内表示定点数无法表示的更大范围的数。 例如,一个指数范围为±4的4位十进制浮点数可以用来表示43210,4.321或0.0004321,但是没有足够的精度来表示432.123和43212.3(必须近似为432.1和43210)。当然,实际使用的位数通常远大于4。 此外,浮点数表示法通常还包括一些特别的数值:+∞和?∞(正负无穷大)以及NaN('Not a Number')。无穷大用于数太大而无法表示的时候,NaN则指示非法操作或者无法定义的结果。 大部份计算机采用二进制(b=2)的表示方法。位(bit)是衡量浮点数所需存储空间的单位,通常为32位或64位,分别被叫作单精度和双精度。有一些计算机提供更大的浮点数,例如英特尔公司的浮点运算单元Intel8087协处理器(以及其被集成进x86处理器中的后代产品)提供80位长的浮点数,用于存储浮点运算的中间结果。还有一些系统提供128位的浮点数 浮点数的表示 在实际应用中,往往会使用实数,例如下面的一些十进制实数: 179.2356=0.1792356x10^3 0.000000001=0.1x10^8 3155760000=0.215576x10^6 很明显,上述第一个数既有整数也有小数,不能用定点数格式化直接表示,后两个数则可能超出了定点数的表示范围,所以计算机引入了类似与科学表示法来标示实数。 (1)典型的浮点数格式 在机器中,典型的浮点数格式如图所示 浮点数代码由两部分组成:阶码E和尾数M。浮点数真值为: N=+/-(R^E)xM R是阶码的底。在机器中一般规定R为2,4,8或16,与尾数的基数相同。例如尾数为二进制,则R也为2。同一种机器的R值是固定不变的,所以不需要在浮点数代码中表示出来,他是隐含约定的。因此,机器中的浮点数只需表示出阶码和尾数部分。 E是阶码,即指数值,为带符号整数,常用移码或补码表示。 M是尾数,通常是纯小数,常用原码或补码表示。

计算机中数据的表示与信息编码

计算机中数据的表示与信息编码 计算机最主要的功能是处理信息,如处理文字、声音、图形和图像等信息。在计算机内部,各种信息都必须经过数字化编码后才能被传送、存储和处理。因此要了解计算机工作的原理,还必须了解计算机中信息的表现形式。 1.2.1 计算机使用的数制 1.计算机内部是一个二进制数字世界 计算机内部采用二进制来保存数据和信息。无论是指令还是数据,若想存入计算机中,都必须采用二进制数编码形式,即使是图形、图像、声音等信息,也必须转换成二进制,才能存入计算机中。为什么在计算机中必须使用二进制数,而不使用人们习惯的十进制数?原因在于: ⑴易于物理实现:因为具有两种稳定状态的物理器件很多,例如,电路的导通与截止、电压的高与低、磁性材料的正向极化与反向极化等。它们恰好对应表示1和0两个符号。 ⑵机器可靠性高:由于电压的高低、电流的有无等都是一种跃变,两种状态分明,所以0和1两个数的传输和处理抗干扰性强,不易出错,鉴别信息的可靠性好。 ⑶运算规则简单:二进制数的运算法则比较简单,例如,二进制数的四则运算法则分别只有三条。由于二进制数运算法则少,使计算机运算器的硬件结构大大简化,控制也就简单多了。 虽然在计算机内部都使用二进制数来表示各种信息,但计算机仍采用人们熟悉和便于阅读的形式与外部联系,如十进制、八进制、十六进制数据,文字和图形信息等,由计算机系统将各种形式的信息转化为二进制的形式并储存在计算机的内部。 2.进位计数制 数制,也称计数制,是指用一组固定的符号和统一的规则来表示数值的方法。数制可分为非进位计数制和进位计数制两种。非进位计数制的数码表示的数值大小与它在数中的位置无关;而进位计数制的数码所表示的数值大小则与它在数中所处的位置有关。而我们在这里讨论的数制指的都是进位计数制。 进制是进位计数制的简称,是目前世界上使用最广泛的一种计数方法,它有基数和位权两个要素。 ??基数:在采用进位计数制的系统中,如果只用r个基本符号(例如0,1,2,…,r-1)表示数值,则称其为r数制(Radix-r Number System),r称为该数制的基数(Radix)。如日常生活中常用的十进制,就是r=10,即基本符号为0,1,2,…,9。如取r=2,即基本符号为0和1,则为二进制数。 ??位权:每个数字符号在固定位置上的计数单位称为位权。位权实际就是处在某一位上的1所表示的数值大小。如在十位制中,个位的位权是100,十位的位权是101,…;向右依次是10-1,10-2,…。而二进制整数右数第2位的位权为2,第3位的位权为4,第4位的位权为8。一般情况下,对于r进制数,整数部分右数第i位的位权为r i-1,而小数部分左数第i位的位权为r-i。 各种进制的共同点是: ⑴每一种数制都有固定的符号集。如十进制数制,其符号有十个:0,1,2, (9) 二进制数制,其符号只有两个:0和1。需要指出的是,16进制数基数为16,所以有16个基本符号,分别为0,1,2,…,8,9,A,B,C,D,E,F。表1-3列出了计算机中常用的几种进制。 ⑵采用位置表示法,用位权来计数。即处于不同位置的数符所代表的值不同,与它所在位置的权值有关。例如:十进制的1358.74可表示为: 1358.74=1×103+3×102+5×101+8×100+7×10-1+4×10-2 可以看出,各种进位制中的位权的值恰好是基数的某次幂。因此,对于任何一个进位计数制表示的数都可以写出按其权值展开的各项式之和,称为“按权展开式”。任意一个n位整数和m位小数的r进制数D可表示为:

浮点数的表示和运算(范围计算)

浮点数的表示和运算 浮点数的表示和基本运算 1 浮点数的表示 通常,我们可以用下面的格式来表示浮点数 其中S是符号位,P是阶码,M是尾数 对于IBM-PC而言,单精度浮点数是32位(即4字节)的,双精度浮点数是64位(即8字节)的。两者的S,P,M所占的位数以及表示方法由下表可知 以单精度浮点数为例,可以得到其二进制的表示格式如下 其中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 那么这些值是如何求出来的呢?

相关文档
最新文档