二进制转换器10011001对应的十进制转换器数153怎么算

二进制 八进制000 11 10 6111 7 在把二进制数转换为八进制表示形式时,对每三位二进制位进行分组,应该从小数点所在位置分别向左向右划分,若整数部分倍数不是3的倍数,可以在最高位前面补若干个0;对小数部分,当其位数不是的倍数时,在最低位后补若干个0.然后从左到右

从后到前 每三位做为一个单位 如 10 000 011 111 如果第一组不够 则补0 这个数转换成8进制 就是 2 0 5 7

本篇的目的就是为了让更多的人了解浮点数存储的基本原理,还是那句话,学习的同时带着思考。同样这里不讨论浮点数的精度损失和数值的计算理论。直接讲实质的表现。

上节讲到,C语言中的小数可以使用指数形式来表示,即aEnaen,它等价于a×10n

在内存中,小数也是以指数形式来表示的,但又和C语言中的有所区别。小数在被存储到内存前,首先转换为下面的形式:

a 为尾数,是二进制形式,且 1 ≤ a < 2;n 为指数,是十进制形式。

其中,2 是固定的,不需要在内存中体现出来;正负号、指数(n)、尾数(a) 是变化的,需要占用内存空间来表示。这样,float、double 在内存中就被分成了三部分,如下图所示:

例如对于 19.625,整数部分的二进制形式为:

小数部分的二进制形式为:

将整数部分和小数部分合并在一起:

由于尾数 a 必须 1 ≤ a < 2,所以还需要再将小数点向左移动4位:

所有的小数被转换成指数形式后,尾数的整数部分都为1,无需在内存中提现出来,所以干脆将其截去,只把小数点后面的二进制放入内存中的尾数部分(23Bits)。对于 1.0011101,尾数部分就是 0011101。C语言把整数作为定点数,而把小数作为浮点数。定点数必须转换为补码再写入内存,浮点数没有这个过程,直接写入原码。小数被转换成指数形式后,指数有正有负,在内存中不但要能表现其值,还要能表现其正负。而指数是以原码形式存储的,没有符号位,所以要设计一个巧妙的办法来区分正负。对于 float,指数占用8Bits,能表示从 0000。下面我们使用代码来验证一下:

C语言不能直接输出二进制形式,一般输出十六进制即可,十六进制能够很方便地转换成二进制。

精度指测量值与真实值的接近程度,在C语言中表现为输出值和真实值的接近程度。

float 和 double 的精度是由尾数的位数决定。内存中的尾数只保存了小数点后面的部分,其整数部分始终是一个隐含着的“1“,它是不变的,不会对精度造成影响。float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即 float 的精度为 6~7

当小数的尾数部分过长时,多出的位数就会被直接截去,这时保存的就不是小数的真实值,而是一个近似值。在上节的示例中,我们看到 128.101 的输出结果就是一个近似值。128.101 11。下面的代码有力地证明了这一点:

在计算机发展过程中,我们使用的小数和实数曾经提出过很多种的表示方法。典型的比如相对于浮点数的定点数(Fixed Point Number)。在这种表达方式中,小数点固定的位于实数所有数字中间的某个位置。货币的表达就可以使用这种方式,比如 88.22 或者 22.88 可以用于表达具有四位精度(Precision),小数点后有两位的货币值。由于小数点位置固定,所以可以直接用四位数值来表达相应的数值。SQL 中的 NUMBER 数据类型就是利用定点数来定义的。还有一种提议的表达方式为有理数表达方式,即用两个整数的比值来表达实数。

很显然,上面的定点数表示法有缺陷,不能表示很小的数或者很大的数。于是,为了解决这种问题,我们的前辈们自然想到了科学技术法的形式来表示,即用一个尾数(Mantissa ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。比如 123.456 用十进制科学计数法可以表达为 1.23456 × 102 ,其中 1.23456 为尾数,10 为基数,2 为指数。浮点数利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数。

大约就在1985年,IEEE标准754的推出,它是一个仔细制定的表示浮点数及其运算的标准。这项工作是从1976年Intel发起8087的设计开始的,8087是一种为8086处理器提供浮点支持的芯片,他们雇佣了William Kahan,加州大学伯克利分校的一位教授,作为帮助设计未来处理器浮点标准的顾问。他们支持Kahan加入一个IEEE资助的制订工业标准的委员会。这个委员会最终采纳了一个非常接近于Kahan为Intel设计的标准。目前,实际上所有的计算机够支持这个后来被称为IEEE浮点(IEEE floating point)的标准。这大大改善了科学应用程序在不同机器上的可移植性。所谓IEEE就是电器和电子工程师协会。

介绍完了历史,先来看看浮点数最直接的表示。在数学上:

上面简单的描述了在数学意义上的浮点数表示,但是在计算机中,我们存放在内存中的直观上看16进制数,那么这些16进制数是怎么表示我们浮点数的二进制形式呢?

在 IEEE 标准中,浮点数是将特定长度的连续字节的所有二进制位分割为特定宽度的符号域,指数域和尾数域三个域,其中保存的值分别用于表示给定二进制浮点数中的符号,指数和尾数。这样,通过尾数和可以调节的指数(所以称为"浮点")就可以表达给定的数值了。具体的格式:

我们都知道浮点数在32位机子上有两种精度,float占32位,double占64位。很多朋友喜欢把double用于8字节的数据存储。从这点我们应该不要特殊看到浮点数的内存存储形式,他跟整数没有什么区别,只是在这4字节或者8字节里有3个区域,整数有符号只有符号位及后面的数值,之所以最高位表示有符号数的符号位。原因之一在于0x7fffffff位最大整数,为整个32位所能表示的最大无符号整数0xffffffff的一半减一,也就是:比如1字节:无符号是:0xff,有符号正数为:(0, 127],负数为[-128, 0)。在8位有符号时,肯定内存值大于等于: 0x80。二进制就是,比他大,只会在低7位上变化,最高位已经是1了,变了就变小了。所以这里也是一个比较巧用的地方,一举两得。

那么,我们先来看32位浮点数 的换算:

1. 从浮点数到16进制数

就这个浮点数,我们一步一步将它转换为16进制数。

首先,整数部分5,4位二进制表示为:0101。

其次,小数部分0.2,我们应该学了小数转换为二进制的计算方法,那么就是依次乘以2,取整数部分作为二进制数,取小数部分继续乘以2,一直算到小数结果为0为止。那么对0.2进行计算:

因此,这里把0.2的二进制就计算出来了,结果就为:0.... ... 这里的省略号是你没有办法计算完。二进制序列无限循环,没有到达结果为0的那一天。那么此时我们该怎么办?这里就得取到一定的二进制位数后停止计算,然后舍入。我们知道,float是32位,后面尾数的长度只能最大23位。因此,计算结束的时候,整数部分加上小数部分的二进制一共23位二进制。因此5.2的二进制表示就为:

此时,使用科学计数法表示,结果为:

由于我们规定,使用二进制科学计数法后,小数点左边必须为1(肯定为1嘛,为0的话那不就是0.xxxx*sxxx 了,这样没有什么意义),这里不能为0是有一个很大的好处的,为什么?因为规定为1,这样这个1就不用存储了,我们在从16进制数换算到浮点数的时候加上这个1就是了,因为我们知道这里应该有个1,省略到这个1的目的是为了后面的小数部分能够多表示一位,精度就更高一些了哟。那么省略到小数点前面的1后的结果为:

这里后面蓝色的0就是补上的,这里不是随便补的一个0,而是0.2的二进制在这一位上本来就应该为0,如果该为1,我们就得补上一个1.是不是这样多了一位后,实际上我们用23位表示了24位的数据量。有一个位是隐藏了,固定为1的。我们不必记录它。

但是,在对阶或向右规格化时,尾数要向右移位,这样被右移的尾数的低位部分会被丢掉,从而造成一定的误差,因此要进行舍入处理。 常用的舍入方法有两种:一种是“0舍1入”法,即如果右移时被丢掉数位的最高位为0则舍去,为1则将尾数的末位加“1”,另一种是“恒置1”,即只要数位被移掉,就在尾数的末位恒置“1”。

后面还有依次为01...等低位,由于最高位的1会被隐藏,向后扩展一位如果不做舍入操作则结果为:

但是经过舍入操作后,由于被舍掉的位的最高位是1,或者“恒置1”法,最后面的0都应该是1。因此最终就应该是:

在这里需要说明,不管是恒置1,还是0舍1入法,其根本都是为了减小误差。

好了,尾数在这里就计算好了,他就是  

再来看阶数,这里我们知道是2^2次方,那么指数就是2。同样IEEE标准又规定了,因为中间的 阶码在float中是占8位,而这个 阶码又是有符号的(意思就是说,可以有2^-2次方的形式)。

一共就是31位了,这里还差一位,那就是符号位,我们定义的是5.2,正数。因此这里最高位是0,1表示负数。

到这里,我们内存里面的十六进制数产生了,分开来看:

因此,我们看到的就是0x40A66666, 此就是5.2最终的整数形式。

2.从十六进制数到浮点数

我们还是可以用上面5.2的例子,再将0x40A66666换算回去,用同样一个例子,结果更直观,逆运算更好理解。那我们就开始吧。

首先,要还原回去,必须将这个16进制用我们的计算器换算成二进制:

我是COPY上面的。这里颜色已经很明显了,我划分成了3个区域 。 

首先确定符号,这里是0,因此是正数。

其次看绿色的8位,换成10进制就是:12910

我们逆运算,知道这里需要129 - 127 = 2得到指数,得到了指数,我们便知道我们小数点是向哪个方向移动了好多位。脑子里已经有了一个科学计数法的锥形。

再次把红色的23位提取出来,这里不把它换成10进制,因为我们指数是表示的二进制上移动了多少位,底数是2,而不是10。

这里因为之前我们都知道有个固定的1给省略了,因此这里要给加上去。加上去之后:

这里是24位,我们先不管,小数点添进去:

然后将科学计数法变换成普通的二进制小数:

到这里,就真正可以把整数部分换成十进制了:

我们知道了,整数部分是5,后面的小数部分再进行逆运算:

这里我们就应该想想小数到二进制数是乘法,这里逆运算就应该除以2,因此就可以表示为:

因此我们可以看到精度已经有损失了。

问题一:写写-5.2的16进制数?

首先,0.5整数部分为0,这里就不处理了。

其次,0.5小数部分,二进制表示为:0.1

这里是0.1,将尾数补满23位则是:

由于小数点左边是0,因此需要向右移动一位 ,因此:

这里1又被省略掉,所以23位全部变成了0 ,因此:

这样一来,阶码就有了,由于又是正数,那么组合起来:

这样一来,最终的16进制数则为:0x3f000000.

这里就不再具体说明怎么换算的了,只需要提到2个地方:

一是,中间的阶码在double中占有11位,因此就不是+127了,而是加上1023,因为11位能表示的最大无符号数是2047,因此有符号范围[-]。

二是,尾数是52位,因此精度更高,能表示的数也就越大。我们在换算5.2的时候,后面的小数二进制+前面的5的二进制再省略一位后的总位数要填满52位。

好了,浮点数也没有太多要说的,就到这里吧,在用的时候注意精度和范围就可以了。

观察这几个数,加深一下那三个域的计算方式,并说出这些数据有什么规律?

我要回帖

更多关于 进制转换器 的文章

 

随机推荐