2012-02-28 3 views
0

Je vais avoir des problèmes avec addition à virgule flottante en C.Addition Virgule flottante en C

On nous donne deux 16 numéros de bits, nous sommes censés les ajouter ne pas se soucier des cas où leurs signes sont différents ou où les exposants sont 0 ou 31.
Ceci est un devoir, mais je suis en retard & Je ne peux pas comprendre pourquoi cela ne fonctionne pas.

Le Algrothim ressemble un peu comme:

  1. Recupere les bits de signe de chaque numéro, si leur retour différent 0.
  2. Obtenez les exposants de chaque numéro, trouver le plus gros 2a. découvrez la différence entre les deux.
  3. dans le 11 bit mis dans une implicite un dans chacun des
  4. droite déplacer le numéro du mantisse avec l'exposant plus petit par la différence des exposants
  5. Prenez le signe et l'exposant du plus grand nombre ou avec le mantisse décalée.
  6. Renvoie le résultat.

Voici mon code:

LC3_Word FLADD(LC3_Word A, LC3_Word B) 
{ 
    // a debug variable, so we can turn errors on (debug = 1) and off (debug = 0) 
    int debug = 1; 

    // a default return value 
    LC3_Word returnValue = 0x0000; 

    if(debug) 
    { 
     printf("-----------------------------------\nBegin debug\n-----------------------------------\n"); 
     printf("Return value: %x \n",returnValue); 
     printf("LC3 words: A %x, B %x\n",A,B); 
    } 

    // Masks to extract sign, exponent and fraction 
    LC3_Word signBitMask = 0x8000; 
    LC3_Word expMask = 0x7C000; 
    LC3_Word mantissaMask = 0x03FF; 

    // Mask to get the sign with the exponent 
    LC3_Word signExpMask = 0xFC00; 

    // A mask for the implicit 1 
    LC3_Word implicitOne = 0x0400; 

    // Getting the signs 
    LC3_Word signA = AND(signBitMask,A); 
    LC3_Word signB = AND(signBitMask,B); 

    // Getting the exponents 
    LC3_Word expA = AND(expMask,A); 
    LC3_Word expB = AND(expMask,B); 

    // Getting the mantissa's 
    LC3_Word mantA = AND(mantissaMask,A); 
    LC3_Word mantB = AND(mantissaMask,B); 

     if(debug) 
     { 
      printf("======================\n"); 
      printf("\tSignBitMask: %x\n\texpMask: %x\n\tmantissaMask: %x\n",signBitMask,expMask,mantissaMask); 
      printf("\tSign EXP Mask: %x\n",signExpMask); 
      printf("\tsignA: %x, signB: %x\n", signA, signB); 
      printf("\tImplicit One Mask: %x\n",implicitOne); 
      printf("\tExp of a: %x, Exp of b: %x\n", expA, expB); 
      printf("\tmantissa of A: %x,mantissa of B: %x\n",mantA,mantB); 
      printf("======================\n"); 
     } 

    // Getting each with it's sign bit and it's exponent 
    LC3_Word signExpA = AND(signExpMask,A); 
    LC3_Word signExpB = AND(signExpMask,B); 

     if(debug) 
     { 
      printf("signExpA of A: %i, signExpB of B: %i\n",signExpA,signExpB); 
     } 

    // if the signs are different, don't deal with this case 
    if(signA!=signB) 
    { 
     return 0; 
    } 

    // if the signs are the same, if not, just return the default value 
    if(signA==signB) 
    { 
     if(debug) 
     { 
      printf("We got into the if signs are the same block \n"); 
      printf("Sign a: %i, Sign b: %i \n",signA,signB); 
     } 

     if(expA==expB) 
     { 
      if(debug) 
      { 
       printf("We got into the if exponents are the same block \n"); 
       printf("Exp a: %x, Exp b: %x \n",expA,expB); 
      } 

      // exponents are the same 
      // Add Mantissa B to A 
      mantA = ADD(mantB,mantA); 
      if(debug) 
      { 
       printf("Addition of mantissa's %x\n",mantA); 
      } 
      // store into the return value the logical and of the mantissa with the existing exponent and sign 
      // might want to do an OR() not an AND() 
      returnValue = OR(signExpA,mantA); 
     } // end if the eponents are the same 
     else { 
      if(debug) 
      { 
       printf("The exponents are not the same block \n"); 
      } 
      // Getting the size we need to shift by 
      int sizeToShift = 0; 
      if(expA>expB) 
      { 
       // Mask the mantissa of B with a implicit 1, then right shift 
       mantB = OR(implicitOne,mantB); 

       if(debug) 
       { 
        printf("The exponent a is > b\n"); 
       } 
       // need to shift B, getting the size of how much 
       sizeToShift = expA-expB; 

       if(debug) 
       { 
        printf("size to shift: %d,\nmantissaB is: %x\n",sizeToShift,mantB); 
       } 
       // right shifting the mantissa of b 
       mantB = mantB >> sizeToShift; 

       if(debug) 
       { 
        printf("mantissa of b shifted: %x\n",mantB); 
       } 
       returnValue = OR(signExpA,ADD(mantA,mantB)); 
      }// end if A > B in the exponent 
      else 
      { 
       // Mask the mantissa of A with a implicit 1, then right shift 
       mantA = OR(implicitOne,mantA); 
       if(debug) 
       { 
        printf("The exponent B is > A\n"); 
       } 
       // need to shift A, getting the size of how much 
       sizeToShift = expB-expA; 

       if(debug) 
       { 
        printf("size to shift: %d,\nmantissaA is: %x\n",sizeToShift,mantA); 
       } 
       // right shifting the mantissa of A 
       mantA = mantA >> sizeToShift; 

       if(debug) 
       { 
        printf("mantissa of A shifted: %x\n",mantA); 
       } 
       returnValue = OR(signExpB,ADD(mantA,mantB)); 
      }// end if B > A in the exponent   
     }// end if different exponents 
    } // end if the signs are the same 

    if(debug) 
    { 
     printf("Return Value %x\n",returnValue); 
     printf("-----------------------------------\nEnd debug\n-----------------------------------\n"); 
    } 

    return returnValue; 
} 

Voici ADD, OR et AND,

LC3_Word AND(LC3_Word A, LC3_Word B) 
{ 
    return (A&B); 
} 

LC3_Word OR(LC3_Word A, LC3_Word B) 
{ 
    return (A|B); 
} 

LC3_Word ADD(LC3_Word A, LC3_Word B) 
{ 
    return (A+B); 
} 

Quand j'ajouter 2 + 3 en virgule flottante je reçois 3 au lieu de 5.

Des idées?

+0

Ce sont des valeurs à virgule flottante 16 bits? Si oui, n'avez-vous pas trop de zéros sur votre expMask? –

+1

Après un bref coup d'œil, il semble que vous ne teniez pas compte du "1" implicite dans le chemin simple où les exposants sont égaux. –

+0

Vous ne devriez pas utiliser une variable séparée pour le débogage comme ça. Il peut consommer de la mémoire et/ou du CPU.Et s'il y a des centaines de variables à différents endroits? Avez-vous l'intention de les modifier tous? Utilisez '# define' et' # ifdef' à la place, ils seront gérés par le préprocesseur et seront supprimés si nécessaire car ils n'ont jamais existé dans le code –

Répondre

1
if(expA==expB) 
    { 
     if(debug) 
     { 
      printf("We got into the if exponents are the same block \n"); 
      printf("Exp a: %x, Exp b: %x \n",expA,expB); 
     } 

     // exponents are the same 
     // Add Mantissa B to A 
     mantA = ADD(mantB,mantA); 
     if(debug) 
     { 
      printf("Addition of mantissa's %x\n",mantA); 
     } 
     // store into the return value the logical and of the mantissa with the existing exponent and sign 
     // might want to do an OR() not an AND() 
     returnValue = OR(signExpA,mantA); 
    } // end if the eponents are the same 

Ceci est faux.

Vous ne parvenez pas à comptabiliser l'ajout des deux implicites. Lorsque vous ajoutez 2 + 3, vous ajoutez 1,0 x 2^1 + 1,1 x 2^1 et vous ignorez tout avant le point décimal ... Donc vous finissez par 0,0 + 0,1 = 0,1 1 à l'avant. Vous devez également ajouter les deux implicites.

Essayez quelque chose comme ceci:

if(expA==expB) 
    { 
     if(debug) 
     { 
      printf("We got into the if exponents are the same block \n"); 
      printf("Exp a: %x, Exp b: %x \n",expA,expB); 
     } 

     // exponents are the same 
     // Add Mantissa B to A 
     mantA = OR(implicitOne,mantA); 
     mantB = OR(implicitOne,mantB); 

     mantA = ADD(mantB,mantA); 

     // You need to normalize this now. But shifting to the right by 1 will suffice. 
     mantA >>= 1; 
     ++expA; 
     // ... add the sign and you're done... 

     if(debug) 
     { 
      printf("Addition of mantissa's %x\n",mantA); 
     } 
     // store into the return value the logical and of the mantissa with the existing exponent and sign 
     // might want to do an OR() not an AND() 
     returnValue = OR(signExpA,mantA); 
    } // end if the eponents are the same 
0

Je lis encore dans le code mais ne devrait pas

LC3_Word expMask = 0x7C000;

être

LC3_Word expMask = 0x7c00 ;?

De même, pouvez-vous coller des représentations binaires de vos nombres? Juste pour que nous soyons clairs sur ce qui est mis à travers cet algorithme. Le bug pourrait aussi être dans votre code de conversion si vous en utilisez un ...