将C中的浮点数转换为IEEE标准

时间:2013-03-06 04:17:02

标签: c

我试图在C中编写一个生成随机整数的代码,执行简单的计算,然后我尝试在IEEE标准中打印文件的值。但我无法这样做,请帮助。

我无法以十六进制/二进制打印,这非常重要。 如果我在fprintf中输入值,我会收到此错误expected expression before double

int main (int argc, char *argv) {

     int limit = 20 ; double a[limit], b[limit];                //Inputs
     double result[limit]    ; int i , k ;            //Outputs
     printf("limit = %d", limit ); double q;


     for (i= 0 ; i< limit;i++)
         {
         a[i]= rand();
         b[i]= rand();
         printf ("A= %x B = %x\n",a[i],b[i]);

         }

     char op;

      printf("Enter the operand used : add,subtract,multiply,divide\n"); 
     scanf ("%c", &op); switch (op) {

     case '+': {
             for (k= 0 ; k< limit ; k++)
                 {

                 result [k]= a[k] + b[k];
            printf ("result= %f\n",result[k]);

                 }
             }
         break;

     case '*': {
             for (k= 0 ; k< limit ; k++)
                 {

                 result [k]= a[k] * b[k];

                 }
             }
         break;

     case '/': {
             for (k= 0 ; k< limit ; k++)
                 {

                 result [k]= a[k] / b[k];

                 }
             }
         break;

     case '-': {
             for (k= 0 ; k< limit ; k++)
                 {

                 result [k]= a[k] - b[k];

     }
             }
         break; }


     FILE *file; file = fopen("tb.txt","w"); for(k=0;k<limit;k++) {  
     fprintf (file,"%x\n
     %x\n%x\n\n",double(a[k]),double(b[k]),double(result[k]) );

     }


     fclose(file); /*done!*/
 }

3 个答案:

答案 0 :(得分:3)

如果您的C编译器直接支持IEEE-754浮点格式(因为CPU支持它)或完全模拟它,您可以将doubles简单地打印为字节。这就是x86 / 64平台的情况。

以下是一个例子:

#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <float.h>

void PrintDoubleAsCBytes(double d, FILE* f)
{
  unsigned char a[sizeof(d)];
  unsigned i;
  memcpy(a, &d, sizeof(d));
  for (i = 0; i < sizeof(a); i++)
    fprintf(f, "%0*X ", (CHAR_BIT + 3) / 4, a[i]);
}

int main(void)
{
  PrintDoubleAsCBytes(0.0, stdout); puts("");
  PrintDoubleAsCBytes(0.5, stdout); puts("");
  PrintDoubleAsCBytes(1.0, stdout); puts("");
  PrintDoubleAsCBytes(2.0, stdout); puts("");
  PrintDoubleAsCBytes(-2.0, stdout); puts("");
  PrintDoubleAsCBytes(DBL_MIN, stdout); puts("");
  PrintDoubleAsCBytes(DBL_MAX, stdout); puts("");
  PrintDoubleAsCBytes(INFINITY, stdout); puts("");
#ifdef NAN
  PrintDoubleAsCBytes(NAN, stdout); puts("");
#endif
  return 0;
}

输出(ideone):

00 00 00 00 00 00 00 00 
00 00 00 00 00 00 E0 3F 
00 00 00 00 00 00 F0 3F 
00 00 00 00 00 00 00 40 
00 00 00 00 00 00 00 C0 
00 00 00 00 00 00 10 00 
FF FF FF FF FF FF EF 7F 
00 00 00 00 00 00 F0 7F 
00 00 00 00 00 00 F8 7F 

如果不直接支持IEEE-754,则问题会变得更加复杂。但是,它仍然可以解决。

以下是一些可以提供帮助的相关问题和答案:

当然,所有IEEE-754相关信息都可以在Wikipedia中找到。

答案 1 :(得分:1)

在你的fprint部分试试这个:

fprintf (file,"%x\n%x\n%x\n\n",*((int*)(&a[k])),*((int*)(&b[k])),*((int*)(&result[k])));

这会将double转换为整数,因此它以IEEE标准打印。

但是如果你在32位机器上运行你的程序,int是32位且double是64位,我想你应该使用:

fprintf (file,"%x%x\n%x%x\n%x%x\n\n",*((int*)(&a[k])),*((int*)(&a[k])+1),*((int*)(&b[k])),*((int*)(&b[k])+1),*((int*)(&result[k])),*((int*)(&result[k])+1));

答案 2 :(得分:1)

在C中,有两种方法可以获取浮点值中的字节:指针强制转换或联合。我推荐一个工会。

我刚刚用GCC测试了这段代码并且有效:

#include <stdio.h>
typedef unsigned char BYTE;

int
main()
{
    float f = 3.14f;
    int i = sizeof(float) - 1;
    BYTE *p = (BYTE *)(&f);
    p[i] = p[i] | 0x80;  // set the sign bit
    printf("%f\n", f);  // prints -3.140000
}

我们正在获取变量f的地址,然后将其分配给指向BYTE(unsigned char)的指针。我们使用强制转换强制指针。

如果您尝试编译启用了优化的代码并执行上面显示的指针转换,则可能会遇到抱怨“类型错误指针”问题的编译器。我不确定你什么时候能做到这一点,什么时候做不到。但是你总是可以使用另一种方法来获取位:将float放入带有字节数组的并集中。

#include <stdio.h>

typedef unsigned char BYTE;

typedef union
{
    float f;
    BYTE b[sizeof(float)];
} UFLOAT;

int
main()
{
    UFLOAT u;
    int const i = sizeof(float) - 1;

    u.f = 3.14f;
    u.b[i] = u.b[i] | 0x80;  // set the sign bit
    printf("%f\n", u.f);  // prints -3.140000
}

工作肯定会尝试将浮点值直接转换为无符号整数或类似的东西。 C不知道您只想覆盖该类型,因此C尝试转换该值,从而导致舍入。

float f = 3.14;
unsigned int i = (unsigned int)f;

if (i == 3)
    printf("yes\n"); // will print "yes"

P.S。在这里讨论“类型惩罚”指针:

Dereferencing type-punned pointer will break strict-aliasing rules