1
回答
解惑IEEE754 浮点数内存布局
华为云7大明星产品0元使用! >>>   

        这几天,群里看到有初学者在询问float的相关内容。大家给他的答复就是自己网上搜内存布局的帖子, 我事后也看了下,发现很多帖子写的都很迷糊。今天,我想和各位同学一起深入的看下754浮点布局状况。下面是我们今天需要调试的程序,由于程序很短所以直接贴图。

 

 

在开始分析之前, 我想把我的参考网址贴一下http://steve.hollasch.net/cgindex/coding/ieeefloat.html

 

我们先来看看图1

 

以及对于 上述的节选描述

 

The Sign Bit

The sign bit is as simple as it gets. 0 denotes a positive number; 1 denotes a negative number. Flipping the value of this bit flips the sign of the number.

The Exponent

The exponent field needs to represent both positive and negative exponents. To do this, abias is added to the actual exponent in order to get the stored exponent. For IEEE single-precision floats, this value is 127. Thus, an exponent of zero means that 127 is stored in the exponent field. A stored value of 200 indicates an exponent of (200-127), or 73. For reasons discussed later, exponents of -127 (all 0s) and +128 (all 1s) are reserved for special numbers.

For double precision, the exponent field is 11 bits, and has a bias of 1023.

The Mantissa

The mantissa, also known as the significand, represents the precision bits of the number. It is composed of an implicit leading bit and the fraction bits.

To find out the value of the implicit leading bit, consider that any number can be expressed in scientific notation in many different ways. For example, the number five can be represented as any of these:

        5.00 × 100
        0.05 × 102
        5000 × 10-3

In order to maximize the quantity of representable numbers, floating-point numbers are typically stored innormalized form. This basically puts the radix point after the first non-zero digit. In normalized form, five is represented as 5.0 × 100.

A nice little optimization is available to us in base two, since the only possible non-zero digit is 1. Thus, we can just assume a leading digit of 1, and don't need to represent it explicitly. As a result, the mantissa has effectively 24 bits of resolution, by way of 23 fraction bits.

 

Sign

相信大家都很清楚 是一个符号位。存在第31位(下标)

Exponent

它其实是一个指数 注意底数是2。 相信大家看过参考资料 一定会奇怪 为什么指数明明有8位, 而表示的范围确是-126 到127 (假如第8位是符号位,不应该是signed char 的范围 -128到 127么?) 这也是我的一个疑问之一。指数的表示范围 是[30-23] 注意方框里位数的顺序 里面是有玄机的 

Mantissa

我们的表格中 写的是 fraction (我英语不好,作者是不是有点坑爹) 尾数 占23位 [22-00]位 同样的 注意方框里的位数顺序

 

Bias

偏移量(硬指标,我也没法解释不过通过下面的解析可能看出点名堂)

 

另外 我贴下重点的总结部分

 

Putting it All Together

So, to sum up:

  1. The sign bit is 0 for positive, 1 for negative.
  2. The exponent's base is two.
  3. The exponent field contains 127 plus the true exponent for single-precision, or 1023 plus the true exponent for double precision.
  4. The first bit of the mantissa is typically assumed to be 1.f, where f is the field of fraction bits.

 

1. 就是 符号位的那点破事

2 就是指数的底数为2

3 这个它说的很模糊 什么叫指数加上一个真指数 太操蛋,(他给的例子中200超出了范围所以-127,而这个范围是多少我想最后的结果肯定不能超过8个1)

另外 我这里主要讨论float 对于double类型方法是一样的,希望大家自己动手试试。补充一点指数为0的时候 是0+127

4 这也是非常关键的一点 , 第一位是从1开始的,因为是二进制数的原因我在下面进行演示。

 

我们回到程序

我们首先按照 上面的资料给出的5.0 *10的0次的表示 来看看反汇编的结果40A00000h(假如对于反汇编的操作不熟悉 请看兵器谱:莫邪2)

然后我们先手动按照上面的标准 算下

5.0 的 二进制 我们先把整数部分 化为 二进制 为 101

然后是小数0.0 化为二进制为 0

二进制为 101.0

那么 按照上面的总结第4条,第一位应该是1, 我们把5.0写成 二进制1.01*2的2次方 指数就是2+127 其二进制为 1000 0001 而尾数部分 我们看到是01 注意它应该先存低位

还是高位呢? (我一开始以为是低位,结果和反汇编的结果不一样,才知道是高位)

那么5.0 它的符号为 应该是0 指数为 就是 1000 0001 尾数位就是01 后面填充0到底

我们拿起计算机 看看40A00000h的二进制是多少?

我的截图如下

貌似 到这里你会觉得豁然开朗, 真的是这样么? 其实5.0f这个数比较特殊的

我们来看看下面一个例子

5.625f

我们依然 按照上面的方法 把 5 转为二进制 101

0.625 转为 二进制 。。。。什么?不会? 好吧,我来补一课。 小数部分10进制转2进制 是*2 取整,然后减去整数部分继续乘2

也就是 0.625 *2 = 1.25 取 1 然后减 1 为0.25

              0.25*2 = 0.5 取 0 减0

             0.5*2 = 1.0 取1 OVER

结果就是 从上往下 读 101 (真的有那么简单么?细心的朋友应该会发现我的例子都是能乘到1.0的)为了方便,我可不想算到23位。这也是精度的计算,计算量大吧?!

结果二进制位101.101

按照IEEE 754的标准 我们写成 1.01101*2的2次方 次数 指数为 2+127 和上面一样1000 0001 而尾数部分 则是 01101000....到最后  符号为是0

我们看看反汇编的16进制数

40B40000

计算器的结果如下

看到这里,你是不是想说 神马 IEEE754 都是浮云 有兴趣的朋友甚至可以能写一个 高精度计算器来 (你要知道 windows自带的计算器面对10进制的小数转2进制结果很悲剧的)

 

当然 我们知道 尾数位 填充的时候是从高位往低位走的 但是 指数位呢? 我们在这里补充一个 例子

我又选了一个 特殊值 1.0f

指数是 0 +127 01111111 好吧我想多了 把这数放进那个该死的8位里

 

另外 什么情况下 需要-127呢? 上面的例子 200就减了, 我想 指数的最大范围 也就是8个1 为255 ,255-127 = 128 相当于128的时候是最大 超过的部分就应该减去 127了, 当然他最后也只能容纳8位,负数同理。

而对于double型,我想也是一个方法。大家私下去试试, 如果哪位前辈发现 文章中有错误,或者对于我的疑问能解答,请不惜吝啬。:)

 


原文链接:http://blog.csdn.net/template_cplus/article/details/7864793
<无标签>
举报
晨曦之光
发帖于5年前 1回/1K+阅
顶部