赞
踩
最近被数值计算的问题困扰,索性做一个梳理,与君分享,温故而知新。
在计算机的世界中,浮点数的表示范围有限。存在无穷多个不能用浮点数表示的数,或者说,浮点数只是近似地表示某一个数。有些情况下0.1+0.2!=0.3。
IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值(无穷∞与非数值NaN),以及这些数值的“浮点数运算符”。 常见的四种浮点数值表示方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。C语言的float通常是指IEEE单精确度,而double是指双精确度。https://zh.wikipedia.org/wiki/IEEE_754zh.wikipedia.org
我以网上能找到的ieee 754 float32在线转换器为例,简单易懂。标准的ieee 754格式由三部分组成,符号位Sign,指数项expoent,以及尾数部分mantissa。它的值可以用
浮点数表示法中指数域的编码值,等于指数的实际值加上某个固定的值,IEEE 754标准规定该固定值为
以单精度浮点数为例,它的指数域是8个比特,固定偏移值是
你肯定心中会问?干嘛要以实际值加上固定的偏移值的办法表示浮点数的指数???其实好处是可以用长度为e个比特的无符号整数来表示所有的指数取值。我们常常把指数部分称为:阶码。
罗列了一下,由于这种阶码+尾数的表示方式,使得浮点数的值形式有多种。
以上规律直接总结为三条:
在此以32位单精度浮点为例,我来列一下这些类别下的数字。懂得了这些规律后,再来看规约数的表达,其实简单的一笔。
类别 正负号 实际指数 有偏移指数 指数域 尾数域 数值
零 0 -127 0 0000 0000 000 0000 0000 0000 0000 0000 0.0
最小规约数 * -126 1 0000 0001 000 0000 0000 0000 0000 0000 ±2−126≈ ±1.18×10-38
最大的规约数 * 127 254 1111 1110 111 1111 1111 1111 1111 1111 ±(2−2−23) × 2127≈ ±3.4×1038
正无穷 0 128 255 1111 1111 000 0000 0000 0000 0000 0000 +∞
好了,在了解数长什么样以后,再来说说舍入的问题。从硬件的角度来说,舍入是因为数bit位宽高于寄存器的bit位宽,那只能将多出来的位丢掉。实际上丢掉的方式有许多。IEEE列出了4种不同的标准:
浮点数的加法运算分成下面步骤:
以0.2+0.4为例:
对阶过程:
0.2 => 0 01111101 (0)11001100110011001100110
0.4 => 0 01111101 (1)10011001100110011001100
尾数求和:
(0)11001100110011001100110 + (1)10011001100110011001100 => (10)01100110011001100110010
尾数规格化:
0 01111101 (10)01100110011001100110010 => 0 01111110 (1)00110011001100110011001
注意0已经被移除了这就是舍入
校验判断
0.2 + 0.4 => 0 01111110 (1)00110011001100110011001 => 1.1999999285/2 => 0.5999999643 (并不等于0.6)
当然知道了这些 还不算,我来说说怎么做乘法。
我以这张图来说明这个过程。
浮点乘法包括符号位异或、指数相加和尾数相乘三部分。
好了说到这儿,谁在提精度问题,直接开启fighting模式。
有关乘法器的内部设计和truncation等近似技术在神经网络冗余计算中的作用,我将在下一篇介绍中进行介绍。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。