ubuntu 64位上的单精度浮点表示不正确

时间:2017-05-31 06:57:26

标签: c ubuntu floating-point 64-bit ieee-754

我有以下数据。

float u[4] = {0x3f951d32, 0x3f207887, 0x3d99c3a0, 0x3eb405d2};
ScaleFunction(u);

void ScaleFunction(float *u_ptr)
{
  for(int i = 0; i < 4; i++)
  {
    printf("u[%d] = %f\n", u_ptr[i]);
  }
  // And a lot more
}

包含上述代码段的应用程序在运行ubuntu 16.10的64位计算机上执行。

令我懊恼的是,浮点数被错误地解释为:1066736960.000000,1059092608.000000,1033487232.000000和1051985344.000000。

以十六进制打印时的数字确认调用者将正确的值传递给被调用者。

我在这里做错了什么?

我甚至没有尝试过以下情况。

uint32_t u[4] = {0x3f951d32, 0x3f207887, 0x3d99c3a0, 0x3eb405d2};
ScaleFunction(u);

void ScaleFunction(uint32_t *u_ptr)
{
  float ut[4];
  for(int i = 0; i < 4; i++)
  {
    ut[i] = (float) u_ptr[i];
    printf("ut[%d] = %f\n", ut[i]);
  }
  // And a lot more
}

我希望将被调用者中的十六进制解释为:     1.1649,0.6628,0.075,0.5516

2 个答案:

答案 0 :(得分:4)

问题是,您使用大整数值初始化数组,而不是浮点数的十六进制表示。你的十六进制常量以0x3f左右的值开头,很明显这些是浮点数据,其值大约为1.0。

据我所知,没有直接的方法来初始化一个带有十六进制常量的float数组(如果有一个,社区,请告诉我!)。

因此,您必须将数据数组定义为int,并在使用时将其转换为float。 重要事项:直接将指针从int转换为float将破坏C的别名规则,并可能导致代码看起来正确但行为异常。

通过memcpy在两种数据类型之间进行转换是安全的,编译器通常足够聪明,可以发现并优化它。

所以这个解决方案可以满足您的需求:

#include <stdint.h>
#include <stdio.h>
#include <string.h>

uint32_t u[4] = {0x3f951d32, 0x3f207887, 0x3d99c3a0, 0x3eb405d2};

void ScaleFunction(uint32_t *u_ptr)
{
  for(int i = 0; i < 4; i++)
  {
      float temp;
      memcpy (&temp, &u[i], sizeof (float));
      printf("u[%d] = %f\n", i, temp);
  }
  // And a lot more
}


void main (int argc, char **args)
{
  ScaleFunction (u);
}

答案 1 :(得分:0)

您的代码无法正常工作:您将整数分配给浮点数。您没有将HEX值指定为float。

你能做的最好的事情就是拥有一个init数组并将其复制到你的float数组

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>

uint32_t init[] = {0x3f951d32u, 0x3f207887u, 0x3d99c3a0u, 0x3eb405d2u};

void ScaleFunction(float *u_ptr, size_t size)
{
  for(size_t i = 0; i < size; i++)
  {
    printf("u[%zu] = %f\n", i, u_ptr[i]);
  }
  // And a lot more
}

int main (void)
{
    assert ( sizeof(float) == sizeof(uint32_t) );

    float u[sizeof(init)/sizeof(init[0])];

    memcpy(u, init, sizeof(init));

    ScaleFunction(u, sizeof(init)/sizeof(init[0]));
}