2

我正在尝试在 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!*/
 }
4

3 回答 3

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中找到。

于 2013-03-06T05:09:33.023 回答
1

在你的 fprint 部分试试这个:

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

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

但是,如果您在int32 位和double64 位的 32 位机器上运行程序,我想您应该使用:

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));

于 2013-03-06T05:03:15.003 回答
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(无符号字符)的指针。我们使用强制转换来强制指针。

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

#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"

PS在这里讨论“类型双关”指针:

取消引用类型双关指针将破坏严格的别名规则

于 2013-03-06T05:28:28.240 回答