2013-03-06 28 views
2

我想在C中编写一个代码,它生成一个随机整数,执行简单计算,然后我试图在IEEE标准中打印该文件的值。但我无法这样做,请帮忙。将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!*/ 
} 
+0

我所需要的值在文本文件中把它与我的硬件设计进行比较。另外,我是C的初学者。我什么都不知道 – chitranna 2013-03-06 04:31:00

+0

一个类型转换语法是'(double)a [k]',但是你将一个double转换为double。大多数时候''%x''需要一个'unsigned int'和'sizeof(double)'可能与'sizeof(unsigned int)'不同。我建议:[Double to Hex string](http://stackoverflow.com/q/497472/260411) – 2013-03-06 04:52:03

回答

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

+0

+1,但对于字节顺序可以说或做些什么。 – 2013-03-06 11:28:45

+0

@EricPostpischil由于图片中有“硬件设计”,我期待OP能够弄明白。 – 2013-03-06 11:30:18

+0

@Alexey Frunze,如果我想订单逆转,我的意思是1(00 00 00 00 00 F0 3F)写为(3F F0 00 00 00 00 00 00)。我会怎么做? – chitranna 2013-03-07 07:25:12

1

在fprint部分试试这个:

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

所以它在IEEE标准打印这将在double转换为整数。

但是,如果你在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));

+1

这种方式转换指针并不能保证C标准。检查对象字节的正确方法是使用联合(根据[本答案](http://stackoverflow.com/a/15239650/298225)上的注释)或指向字符类型的指针(包括使用'memcpy' )。 – 2013-03-06 11:27:16

+0

确实如此,因为sizeof(int)取决于平台。指向char的指针对我的解决方案来说是一个很好的改进,thx提到这一点。 – 2013-03-06 13:21:13

+0

除了对象大小之外,还有更多的考虑因素。不同的对齐要求可能会导致陷阱。编译器进行的优化可能会将不支持的语言使用转换为其他行为。不寻常的机器可能在'int'类型中有陷阱表示('unsigned int'是安全的)。 – 2013-03-06 13:50:16

1

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

我刚刚测试此代码与海湾合作委员会和它的工作:

#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的地址,然后将其分配给一个指针字节(无符号字符)。我们使用强制转换来强制指针。

如果您尝试编译启用优化的代码,并执行上面显示的指针转换,则可能会遇到编译器抱怨“type-punned pointer”问题。我不确定什么时候可以做到这一点,什么时候做不到。但是你总是可以用另一种方式来获取位:将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.的“类型punned”指针在这里讨论:

Dereferencing type-punned pointer will break strict-aliasing rules

+0

使用工会几乎肯定会奏效,但严格来说,访问除最近一个工会会员之外的工会会员不是UB吗?另一方面,我认为转换为char *'是明确定义的。或者,工会案件只是一个延伸? – 2013-03-06 05:41:57

+1

据我所知,C标准没有正式的建议,应该如何访问浮点内的位。我不知道任何有保证和标准的东西。根据我的经验,工会技巧在Windows,Linux,Mac和各种嵌入式处理器(包括DSP处理器)上为我工作。我建议工会,因为它一直为我工作。我希望C在C++中有类似'reinterpret_cast'的东西,你可以明确地告诉编译器“不要做任何事情,只要改变类型”。 – steveha 2013-03-06 05:47:40

+1

我希望我的回答足够清楚,即使我使用'float'而不是'double'。如果有人真的在乎,我想我可以重写它来使用'double'。 – steveha 2013-03-06 05:49:20

相关问题