得到c中浮点数的指数

时间:2017-09-21 08:45:10

标签: c numbers floating

很抱歉,如果已经提出这个问题,我已经看到了提取浮点数的指数的其他方法,不过这是给我的:

# Install locally (in my case: ~/node_modules)
$ npm install phantomjs-prebuilt

# Add to path
$ cd ~/bin
~/bin$ ln -s ../node_modules/phantomjs-prebuilt/bin/phantomjs

# Check if it worked
$ phantomjs --version
2.1.1

我无法理解这个union数据类型,因为最后返回的x.i总是让f2i返回0?

此外,这种数据类型甚至对哪些应用程序有用?例如,假设我有一个功能:

unsigned f2i(float f)
{
  union {
    unsigned i;
    float f;
  } x;
  x.i = 0;
  x.f = f;
  return x.i;
}

这个函数应该得到浮点数的指数值,偏差为127.我已经找到了许多方法使这成为可能,但是我怎么能操纵f2i函数来达到这个目的呢?

我感谢任何指针!

4 个答案:

答案 0 :(得分:1)

因为它是一个联合,这意味着x.ix.f具有相同的地址,这允许您将一种数据类型重新解释为另一种数据类型。在这种情况下,联合首先由x.i = 0;清零,然后填充f。然后返回x.i,它是float f的整数表示。如果您随后移动该值,则会得到原始f的指数,因为float在内存中的布局方式。

答案 1 :(得分:1)

  

我无法理解这个union数据类型,因为最后返回的x.i总是让f2i返回0?

x.i = 0;行有点偏执,不一定是必要的。鉴于unsigned intfloat都是32位,联合在内存中创建一个32位的块,您可以将其作为float或作为float的纯二进制表示,这是unsigned的用途。 (最好使用uint32_t。)

这意味着行x.i = 0;x.f = f;两次写入相同的内存区域。

在函数是float的纯二进制表示法之后,你最终得到了什么。从那里解析指数或任何其他部分是非常多的实现定义,因为它取决于浮点格式和字节顺序。 How to represent FLOAT number in memory in C可能会有所帮助。

答案 2 :(得分:1)

  

我无法理解这个union数据类型

union数据类型是程序员指示某个变量可以是多种不同类型之一的一种方式。 C11标准的措辞类似于“一个联盟至多包含其中一个成员”。它用于诸如逻辑上可以是一个或另一个的参数之类的东西。例如,IP地址可能是IPv4地址或IPv6地址,因此您可以按如下方式定义地址类型:

struct IpAddress
{
    bool isIPv6;
    union 
    {
        uint8_t v4[4];
        uint8_t v6[16];
    } bytes;
}

你会像这样使用它:

struct IpAddress address = // Something
if (address.isIPv6)
{
    doSomeV6ThingWith(address.bytes.v6);
}
else 
{
    doSomeV4ThingWith(address.bytes.v4);
}

历史上,union也被用于将一种类型的位转换为另一种类型的对象。这是因为,在联合中,成员都从相同的内存地址开始。如果我这样做:

float f = 3.0;
int i = f;

编译器将插入代码以将float转换为整数,因此指数将丢失。但是,在

union 
{
    unsigned int i;
    float f;
} x;

x.f = 3.0;
int i = x.i;

i现在包含代表3.0float的确切位。或者至少你希望它能做到。 C标准中没有任何内容表明floatunsigned int必须具有相同的大小。在C标准中也没有要求float的特定表示(嗯,附件F表示浮点符合IEC 60559,但我不知道这是否属于标准的一部分)。所以上面的代码充其量是不可移植的。

要获得float可移植方式的指数,math.h

中定义的frexpf()函数
  

我怎么能操纵f2i功能来达到这个目的呢?

让我们假设float以32位的IEC 60559格式存储,Wkipedia认为这与IEEE 754相同。我们还假设整数以小端格式存储。

union 
{
    uint32_t i;
    float f;
} x;

x.f = someFloat;
uint32_t bits = x.i;

bits现在包含浮点数的位模式。单个精度浮点数看起来像这个

SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
^        ^                     ^
bit 31   bit 22                bit 0

S是符号位,E是指数位,M是尾数位。

所以有了你的int32_t,你只需要做一些转移和掩饰:

uint32_t exponentWithBias = (bits >> 23) & 0xff;

答案 3 :(得分:1)

强烈建议不要使用该联合类型,因为它强烈依赖于体系结构并且依赖于编译器实现....这两种情况使得几乎无法确定实现所请求信息的正确方法。

有可行的方法,并且所有这些方法都必须处理对数十的对数计算。如果你得到log10(x)的整数部分,你将得到你想要的数字,

int power10 = (int)log10(x);

double log10(double x)
{
     return log(x)/log(10.0);
}

会给你10的指数来提高数字乘以尾数得到数字....如果你把原始数字除以最后的结果,你就会得到尾数。

要小心,因为浮点数通常在内部以2的幂存储,这意味着你存储的指数不是10的幂,而是2的幂。