2010-10-03 5 views
2

Je prends un flottant en entrée, puis je renvoie sa représentation équivalente en notation scientifique de base 2. C'est en IEEE 32 bits avec: 31 bits de signe, 23-30 exposant (avec 127 offset), 0-22 mantisse (avec 1 implicite).Algorithme ou code pour la notation scientifique float to base 2 (IEEE 32 bits) en C++?

Une des conditions que je ne suis pas exactement sûr que le sens de "Votre mantisse devrait avoir l'avance implicite 1 pré-ajouté."

Tout ce que j'ai vraiment appris est de décomposer le flottant en ses parties décimales et fractionnaires, et d'obtenir séparément leurs représentations binaires. Comme je ne suis pas sûr de savoir comment faire cela ... Je ne peux pas vraiment le coder. J'apprécierais des conseils ou des informations sur une sorte d'algorithme pour le faire, ou le code lui-même. Merci.

Sample:

Input: -40.1 
Output: -1.01000000110011001100110 E101 

Input: 13.5 
Output: 1.10110000000000000000000 E11 

EDIT: 127 décalage moyen de l'excès de droite notation 127? Mon livre a seulement l'excès 128, mais je ne connais pas la différence de toute façon ...

+2

Il y a une très bonne explication de la façon dont tout cela fonctionne à wikipedia: http://en.wikipedia.org/wiki/IEEE_754-1985 et http://en.wikipedia.org/wiki/Single_precision. – jkerian

+1

Vous pourriez trouver cet article utile: http://www.exploringbinary.com/displaying-ieee-doubles-in-binary-scientific-notation/. J'y montre comment faire cela en C pour les doubles. –

Répondre

0

Vous pouvez tricher, et il suffit d'utiliser frexp.

+1

Je peux seulement # inclure iostream – kevin

+1

@kevin: Est-ce un exercice de devoirs? Si oui, s'il vous plaît ajouter le tag "devoirs" à votre question ... –

+0

Si c'est de la triche, je ne veux pas savoir quelle est la bonne réponse. – Potatoswatter

2

Donc, je ne vais pas faire tout le travail pour vous, parce que cela ressemble à des devoirs. Mais je vais vous aider à démarrer et vous pouvez combler les lacunes. Il existe donc en C++ un type de données pratique appelé union, avec lequel vous pouvez avoir plusieurs types de données occupant le même espace. C'est très utile, si vous voulez voir la représentation en bits d'un nombre à virgule flottante. Le code suivant la sortie de la représentation binaire d'un nombre à virgule flottante:

#include <iostream> 
using namespace std; 
union b{ 
    float flo; 
    int integ; 
}; 
int main(){ 

    b thing; 
    thing.flo=-40.1; 
    for(int i=31;i>=0;i--){ 
    if((thing.integ & (1 << i))) 
     cout << 1; 
    else 
     cout << 0; 
    } 
    cout << endl; 
} 

Tout ce qui reste à faire pour vous est extrait de la mantisse et l'exposant. Vous pouvez exécuter la routine une fois pour générer la mantisse et générer à nouveau l'exposant. Je vais donner une brève explication sur la façon de faire les deux et les choses à surveiller.

Lors de la génération de la mantisse, rappelez-vous que IEEE utilise un 1 caché avec un code réservé pour zéro, donc il y aura toujours un extra qui ne soit pas dans la représentation binaire. Essentiellement, vous allez vérifier l'empreinte du signe - ou + en fonction de cela, puis 1. puis passez à la mantisse et imprimez ce qui suit. Ensuite, vous allez revenir aux 23-30 bits, vous voulez le convertir en un int, pour ce faire multiplier chaque bit par 2^i (23 bits est 0, 24 bit est 1, etc) et vous aurez vouloir soustraire le décalage de l'int. Puis, en utilisant la méthode précédemment décrite, sortie de la représentation binaire de l'exposant, je considérerais pas sortie jusqu'à ce que vous frappez un 1. Espérons que cela aide.

0

Une des manières les plus propres de faire ceci est avec le masquage de bit. Peut-être un meilleur moyen est avec bitfields. Vous pouvez définir une struct pour représenter le format de Floating Point:

struct float_layout { 
    int mantisa : 23 
    int exp : 8 
    int sign : 1 
}; 

obtenez alors votre flotteur, et de le jeter à cette struct:

float b = input; 
float_layout layout = *static_cast<float_layout *>(&b) 

Ce réinterprète les bits de données sans les modifier. Ensuite, vous pouvez facilement accéder aux pièces en tant que numéros. N'oubliez pas d'ajouter le décalage pour exp et ajoutez le premier 1 pour la mantisse.

+0

Bon en principe, mais vous oblige à connaître l'ordre dans lequel 'float's sont stockés sur votre plate-forme. –

+0

J'ai peut-être mal compris le standard, mais je pensais qu'il spécifiait comment il devait être stocké. – JoshD

0
#include <iostream> 

//float:1:8:23, bias 127 
typedef union { 
    float f; 
    unsigned int ui; 
    unsigned char c[4]; 
} Fl_u; 
/*  
bool isLittleEndian(){ 
    Fl_u x; 
    x.f = -0.0; 
    return x.c[3] == 0x80; 
} 
*/ 
void fbinprint(float f){ 
    Fl_u x; 
    unsigned wk=0; 
    x.f = f; 
/* if(isLittleEndian()) 
     for(int i=3;i>=0;--i) 
      wk = (wk << 8) + x.c[i]; 
    else 
*/  wk = x.ui; 
    if(wk & 0x80000000) 
     std::cout << '-'; 
    unsigned bit = wk & 0x07FFFFF; 
    std::cout << "1."; 
    for(int i = 0; i< 23 ; ++i){ 
     bit <<=1; 
     std::cout << (bit & 0x0800000 ? '1' : '0'); 
    } 
    std::cout << " E"; 
    int exp = (wk >> 23) & 0x0FF; 
    exp -= 127;//bias 127 
    if(exp < 0){ 
     std::cout << '-'; 
     exp = -exp; 
    } 
    int i = 0; 
    while((exp & 0x080) == 0 && i < 8){//skip zero of top 
     exp <<= 1; 
     ++i; 
    } 
    if(i == 8) 
     std::cout << '0'; 
    for(;i< 8 ; ++i){ 
     std::cout << (exp & 0x080 ? '1' : '0'); 
     exp <<=1; 
    } 
    std::cout << std::endl; 
} 

int main(){ 
    float f = -40.1; 
    std::cout << "Input: " << f << std::endl; 
    std::cout << "Output: "; 
    fbinprint(f); 
    std::cout << std::endl; 
    f = 13.5; 
    std::cout << "Input: " << f << std::endl; 
    std::cout << "Output: "; 
    fbinprint(f); 
// fbinprint(0.0625); 
} 
Questions connexes