DSP

单精度浮点(32bit float)与半精度浮点(16bit)的理解及开根号求倒数算法

2019-07-13 17:49发布

最近在搞DSP,所以不可避免地会遇到浮点数,包括半精度浮点(16bit) 和单精度浮点(32bit)。 1、根据wiki百科介绍,IEEE 754规范中规定的32bit float point的格式为:(以下引用wiki百科https://en.wikipedia.org/wiki/Single-precision_floating-point_format) Float example.svg The real value assumed by a given 32-bit binary32 data with a given biased sign, exponent e (the 8-bit unsigned integer), and a 23-bit fraction is
{displaystyle (-1)^{b_{31}} imes (1.b_{22}b_{21}dots b_{0})_{2} imes 2^{(b_{30}b_{29}dots b_{23})_{2}-127},}{displaystyle (-1)^{b_{31}}	imes (1.b_{22}b_{21}dots b_{0})_{2}	imes 2^{(b_{30}b_{29}dots b_{23})_{2}-127},}
which in decimal yields
{displaystyle { ext{value}}=(-1)^{ ext{sign}} imes left(1+sum _{i=1}^{23}b_{23-i}2^{-i} ight) imes 2^{(e-127)}.}{displaystyle {	ext{value}}=(-1)^{	ext{sign}}	imes left(1+sum _{i=1}^{23}b_{23-i}2^{-i}
ight)	imes 2^{(e-127)}.},也可以是{egin{aligned}x&=pm 1.b_{1}b_{2}b_{3}ldots 	imes 2^{e_{x}}\&=pm 2^{e_{x}}(1+m_{x})end{aligned}}符号位是最高1位, 指数位,位宽8bit,这8位可以表示为8bit的有符号数,也可以表示为8bit的无符号数,当表示成8bit的无符号数时,指数的实际值 = E(指数表示的值) - 127,127被称为 exponent - bias。这样做之后指数的实际值的范围为 -126 ~ +127,而-127和+128保留做其他用处。 有效位数,也被称为尾数,24bit中最高1bit为隐式存储,且值为1,剩下的23bit显式存储为32bit中的低23bit。 上述计算公式也可以表示为,value = (-1)^sign X 2^(e - 127) X (1 + M / 2^23);(M的值为23bit表示的整数值);
2、而16bit半精度浮点的格式为: sign bit: 1bit exponent width: 5bit significand: 10bit 表示的浮点数值为,alue = (-1)^sign X 2^(e - 16) X (1 + M / 2^10)。
3、单精度浮点的开根号求倒数算法 众所周知的算法是:(引用wiki百科:https://en.wikipedia.org/wiki/Fast_inverse_square_root) float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed return y; } 这个算法应用很广,这里主要是阐述下magic number 0x5f3759df 值的推导
  • Sx, the "sign bit", is 0 if x > 0, and 1 if x < 0 (1 bit)
  • Ex = ex + B is the "biased exponent", where B = 127 is the "exponent bias"[note 3] (8 bits)
  • Mx = mx × L, where L = 223[note 4] (23 bits)
推导过程可参考wiki百科, 最后得出
}{frac {3}{2}}L(B-sigma )={	ext{0x5f3759df}} σ ≈ 0.0450466,按照这个公式计算magic number时可以使用科学计算器,计算出来的小数4舍5入后转为整数,该整数就是magic number

而16bit半精度浮点的magic number的计算也使用该公式,这时L = 2^10,B = 16,最后magic number = 0x5fba (或0x5fbb) 16bit开根号求倒数的代码为:
float16 Q_rsqrt16( float16 number ) { short i; float16 x2, y; const float16 threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( short * ) &y; // evil floating point bit level hacking i = 0x5fba - ( i >> 1 ); // what the fuck? y = * ( float16 * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed return y; }