二进制浮动

时间:2014-04-24 09:41:36

标签: c floating-point binary

我想从二进制表示中生成浮点变量,我很快想出了以下代码:

float bintofloat(unsigned int x) {
    float *f = (float *)&x;
    return *f;
}

然后可以按如下方式调用上述函数:

float f = bintofloat(0x3f800000);

我只是希望对这种方法有一些看法:使用指针是最好的方法,还是有更好或更简洁的方法?

不幸的是,我对类型的使用似乎引起了分心。我为此道歉;为了简单起见,我选择坚持使用内置类型。但我确实认识到这是天真的,并假设sizeof(int) == sizeof(float)

同样,我的主要问题是指针的使用是否是实现从二进制到浮点的转换的好方法?

3 个答案:

答案 0 :(得分:2)

在您的代码中,在函数bintofloat()之后,地址转换和解除引用无效:

float *f = (float *)&x;
return *f;

这将在运行时调用未定义的行为。

  

EXP36-C. Do not cast pointers into more strictly aligned pointer types

     

不要将指针值转换为比引用类型更严格对齐的指针类型。不同类型的对象可以进行不同的对齐。如果类型检查系统被显式强制转换覆盖,或者指针被转换为空指针(void *),然后转换为其他类型,则可以更改对象的对齐方式。

     
    

C标准,6.3.2.3,第7段[ISO / IEC 9899:2011],声明:

         

指向对象或不完整类型的指针可能会转换为指向不同对象或不完整类型的指针。如果生成的指针未针对引用的类型正确对齐,则行为未定义。

  
     

如果取消引用未对齐指针,程序可能会异常终止。在某些体系结构中,如果所涉及的类型具有不同的对齐要求,则单独使用强制转换可能会导致信息丢失,即使该值未被解除引用

在你的代码中x是unsigned int,它具有不同的内存对齐,然后是float类型。

类型转换float *f = (float *)&x;有效但一般不太好。浮点类型指针应指向浮点类型。当将unsigned int *作为float *引用时,某些系统甚至可能给程序一个致命的SIGBUS,因为float需要更严格的地址对齐到sizeof(float)的倍数。

当您编写通用代码的内容时,批准的方式来分配未知类型的地址是使用void*,但是为了解决您必须转换为正确的类型,所以事实上下面的代码是错误的:

unsigned int x = 10U;
unsigned int *xp = &x; 
void* vp = x;
float* fp = vp;
float f = *fp;

我引用的link为您提供了一些有助于您了解问题的示例。

您还应该阅读Keith Thompson的答案:What is the difference between float pointer and int pointer address?

编辑:我认为您可以执行以下操作:

#include<stdio.h>
float bintofloat(unsigned int x) {
    union {
        unsigned int  x;
        float  f;
    } temp;
    temp.x = x;
    return temp.f;
}

int main(){
    float f = bintofloat(0x4236AE14U);
    printf ("\nf = %f ", f);
    printf ("\nf = %f \n", bintofloat(0x4287F0A4U));    
    return 0;
}

将其用作:

$ gcc -Wall -pedantic binarytofloat.c
taxspanner@:~$ ./a.out 

f = 45.669998 
f = 67.970001 

检查以下浮动精度IEEE754计算器的链接:

  1. 0x4236AE14U
  2. 0x4287F0A4U

答案 1 :(得分:1)

首先,您需要了解如何以二进制数表示处理浮点数。遵循标准的IEEE 754转换格式,这将有助于您入门,

http://www.cprogramming.com/tutorial/floating_point/understanding_floating_point_representation.html

http://www.h-schmidt.net/FloatConverter/IEEE754.html

http://kipirvine.com/asm/workbook/floating_tut.htm

答案 2 :(得分:1)

我认为我应该记录我的首选答案是使用memcpy,正如@harold在comment中所建议的那样。不幸的是,我无法直接接受评论作为我问题的答案。

作为参考,使用memcpy的解决方案可能如下所示:

float bintofloat(uint32_t x) {
    float f = 0.0f;
    memcpy(&f, &x, sizeof(f) < sizeof(x) ? sizeof(f) : sizeof(x));
    return f;
}

虽然memcpy解决方案是我的首选答案,但我也想知道另一个很好的解决方案,它建议使用unionhere和{{ 3}}