Met*_*est 41 c floating-point emulation
我有一个程序,它运行在两个处理器上,其中一个没有浮点支持.所以,我需要在该处理器中使用固定点执行浮点计算.为此,我将使用浮点仿真库.
我需要首先在处理器上提取浮点数的符号,尾数和指数,它们支持浮点数.所以,我的问题是如何获得单个精度浮点数的符号,尾数和指数.
按照这个图的格式,
这就是我到目前为止所做的,但除了符号,尾数和指数都不正确.我想,我错过了一些东西.
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;
}
Run Code Online (Sandbox Code Playgroud)
Pie*_*one 25
我的建议是坚持使用规则0而不是重做已经做过的标准库,如果这足够的话.查看math.h(标准C++中的cmath)和函数frexp,frexpf,frexpl,它们在其有效数和指数部分中打破浮点值(double,float或long double).要从有效数字中提取符号,您可以使用signbit,也可以使用math.h/cmath或copysign(仅限C++ 11).一些替代方案,语义不同,是modf和ilogb/scalbn,可在C++ 11中找到; http://en.cppreference.com/w/cpp/numeric/math/logb比较它们,但我没有在文档中找到所有这些函数如何使用+/- inf和NaNs.最后,如果你真的想使用位掩码(例如,你迫切需要知道确切的位,并且你的程序可能有不同的NaN具有不同的表示,并且你不相信上述函数),至少使所有东西都与平台无关通过使用float.h/cfloat中的宏.
era*_*ran 20
我认为使用工会做演员表会更好,但更清楚.
#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);
}
Run Code Online (Sandbox Code Playgroud)
示例基于 http://en.wikipedia.org/wiki/Single_precision
你&错了.我想你想要:
s = *ptr >> 31;
e = *ptr & 0x7f800000;
e >>= 23;
m = *ptr & 0x007fffff;
Run Code Online (Sandbox Code Playgroud)
记住,当你&,你正在将你没有设置的位清零.因此,在这种情况下,您希望在获得指数时将符号位清零,并且希望在获得尾数时将符号位和指数置零.
请注意,面具直接来自您的照片.因此,指数掩码将如下所示:
0 11111111 00000000000000000000000
并且尾数掩码看起来像:
0 00000000 11111111111111111111111
在Linux包上,glibc-headers提供了#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. */
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
88757 次 |
| 最近记录: |