如何获得浮点数的符号,尾数和指数

我有一个程序,它运行在两个处理器上,其中一个没有浮点支持。 所以,我需要在该处理器中使用固定点执行浮点计算。 为此,我将使用浮点模拟库。

我需要首先提取处理器上浮点数的符号,尾数和指数。 所以,我的问题是如何获得单精度浮点数的符号,尾数和指数。

按照这个图的格式,

在这里输入图像描述 这是我迄今为止所做的,但除了符号,尾数和指数都是正确的。 我想,我错过了一些东西。

void getSME( int& s, int& m, int& e, float number ) { unsigned int* ptr = (unsigned int*)&number; s = *ptr >> 31; e = *ptr & 0x7f800000; e >>= 23; m = *ptr & 0x007fffff; } 

我认为使用工会来做演员比较好,这是更清楚的。

 #include <stdio.h> typedef union { float f; struct { unsigned int mantisa : 23; unsigned int exponent : 8; unsigned int sign : 1; } parts; } float_cast; int main(void) { float_cast d1 = { .f = 0.15625 }; printf("sign = %x\n", d1.parts.sign); printf("exponent = %x\n", d1.parts.exponent); printf("mantisa = %x\n", d1.parts.mantisa); } 

基于http://en.wikipedia.org/wiki/Single_precision的示例;

找出直接支持浮点的CPU上使用的浮点数的格式,并将其分解为这些部分。 最常见的格式是IEEE-754 。

或者,您可以使用一些特殊函数( double frexp(double value, int *exp);double ldexp(double x, int exp); )来获得这些部分, 如此答案中所示。

另一个select是使用%aprintf()

我的build议是坚持规则0,而不是重做标准库已经做了什么,如果这是足够的。 查看math.h(标准C ++中的cmath),并且函数frexp,frexpf,frexpl,在其有效数和指数部分中打破浮点值(double,float或long double)。 要从有效数字中提取符号,可以在math.h / cmath或copysign(仅用于C ++ 11)中使用signbit。 一些替代方法,语义不同,是用C ++ 11提供的modf和ilogb / scalbn; http://en.cppreference.com/w/cpp/numeric/math/logb比较他们,但我没有在文档中find所有这些函数如何与+/- inf和NaNs行为。 最后,如果你真的想要使用位掩码(例如,你非常需要知道确切的位,并且你的程序可能有不同的表示forms的NaN,并且你不相信上面的函数),那么至less要把所有的东西做成独立于平台的通过使用float.h / cfloat中的macros。

你是错误的位。 我想你想要:

 s = *ptr >> 31; e = *ptr & 0x7f800000; e >>= 23; m = *ptr & 0x007fffff; 

记住,当你& ,你正在清零你没有设置的位。 所以在这种情况下,当你得到指数的时候,你想把符号位置零,当你得到尾数的时候,你想把符号位和指数归零。

请注意,蒙版直接来自你的照片。 所以,指数掩码将如下所示:

0 11111111 00000000000000000000000

和尾数掩码将如下所示:

0 00000000 11111111111111111111111

在Linux软件包中,glibc-headers提供了带有浮点types定义的头文件#include <ieee754.h> ,例如:

 union ieee754_double { double d; /* This is the IEEE 754 double-precision format. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN unsigned int negative:1; unsigned int exponent:11; /* Together these comprise the mantissa. */ unsigned int mantissa0:20; unsigned int mantissa1:32; #endif /* Big endian. */ #if __BYTE_ORDER == __LITTLE_ENDIAN # if __FLOAT_WORD_ORDER == __BIG_ENDIAN unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1; unsigned int mantissa1:32; # else /* Together these comprise the mantissa. */ unsigned int mantissa1:32; unsigned int mantissa0:20; unsigned int exponent:11; unsigned int negative:1; # endif #endif /* Little endian. */ } ieee; /* This format makes it easier to see if a NaN is a signalling NaN. */ struct { #if __BYTE_ORDER == __BIG_ENDIAN unsigned int negative:1; unsigned int exponent:11; unsigned int quiet_nan:1; /* Together these comprise the mantissa. */ unsigned int mantissa0:19; unsigned int mantissa1:32; #else # if __FLOAT_WORD_ORDER == __BIG_ENDIAN unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; unsigned int negative:1; unsigned int mantissa1:32; # else /* Together these comprise the mantissa. */ unsigned int mantissa1:32; unsigned int mantissa0:19; unsigned int quiet_nan:1; unsigned int exponent:11; unsigned int negative:1; # endif #endif } ieee_nan; }; #define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ 

将一个指针指向浮点variables,就像是一个unsigned int 。 然后你可以移动和掩盖位来获得每个组件。

 float foo; unsigned int ival, mantissa, exponent, sign; foo = -21.4f; ival = *((unsigned int *)&foo); mantissa = ( ival & 0x7FFFFF); ival = ival >> 23; exponent = ( ival & 0xFF ); ival = ival >> 8; sign = ( ival & 0x01 ); 

显然你可能不会使用无符号整数指数和符号位,但这应该至less给你的想法。