2

ランダムな整数を生成し、単純な計算を実行するコードを C で記述しようとしています。次に、IEEE 標準でファイルの値を出力しようとしています。しかし、私はそうすることができません。助けてください。

非常に重要な16進数/2進数で印刷できません。の値を型キャストすると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

doublesC コンパイラが IEEE-754 浮動小数点形式を直接サポートしている場合 (CPU がサポートしているため)、または完全にエミュレートしている場合は、単にバイトとして出力できる場合があります。これは、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

Cでは、float値のバイトを取得する方法が2つあります。ポインターキャストまたはユニオンです。組合をお勧めします。

このコードを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
}

間違いなく機能しないのは、float値を符号なし整数などに直接キャストしようとすることです。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 に答える
1

あなたのfprint部分でこれを試してください:

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

これは整数として変換doubleされるため、IEEE 標準で出力されます。

intしかし、32ビットと64 ビットの 32 ビット マシンでプログラムを実行している場合はdouble、次を使用する必要があると思います。

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 に答える