Je travaille actuellement sur une simulation du processeur MIPS en C++ pour une classe d'architecture compacte et j'ai quelques problèmes pour convertir les nombres décimaux en nombres binaires (nombres signés dans les deux sens). Tout fonctionne bien jusqu'au tout dernier moment car mon algorithme actuel tombe dans les zones hors limites pour int on 1 << = 31. Juste besoin d'un coup de pouce dans la bonne direction pour le rendre opérationnel. Merci!
//Assume 32 bit decimal number
string DecimalToBinaryString(int a)
{
string binary = "";
int mask = 1;
for(int i = 0; i < 31; i++)
{
if((mask&a) >= 1)
binary = "1"+binary;
else
binary = "0"+binary;
mask<<=1;
}
cout<<binary<<endl;
return binary;
}
J'inclus aussi mon autre algorithme pour la complétude. Je m'excuse pour le manque de commentaires, mais c'est assez simple.
int BinaryStringToDecimal(string a)
{
int num = 0;
bool neg = false;
if(a.at(0) == '1')
{
neg = true;
for(int x = a.length()-1; x >= 0; x--)
{
if(a.at(x) == '1')
a.at(x) = '0';
else a.at(x) = '1';
}
a.at(a.length()-1) += 1;
for(int x = a.length()-1; x >= 0; x--)
{
if(a.at(x) == '2')
{
if(x-1 >= 0)
{
if(a.at(x-1) == '1')
a.at(x-1) = '2';
if(a.at(x-1) == '0')
a.at(x-1) = '1';
a.at(x) = '0';
}
}
else if(a.at(x) == '3')
{
if(x-1 >= 0)
a.at(x-1) += '2';
a.at(x) = '1';
}
}
if(a.at(0) == '2')
a.at(0) = '0';
else if(a.at(0) == '3')
a.at(0) = '1';
}
for(int x = a.length()-1; x >= 0; x--)
{
if(a.at(x) == '1')
num += pow(2.0, a.length()-x-1);
}
if(neg)
num = num*-1;
return num;
}
De plus, si quelqu'un connaît des méthodes efficaces pour les écrire plus efficacement, j'aimerais les entendre. Je n'ai suivi que deux cours d'initiation à la programmation, mais j'ai utilisé différentes techniques pour voir à quel point j'aime leur style.
Il existe en réalité des one-liners standard pour ceux-ci.
#include <bitset>
std::string s = std::bitset< 64 >( 12345 ).to_string(); // string conversion
std::cout << std::bitset< 64 >( 54321 ) << ' '; // direct output
std::bitset< 64 > input;
std::cin >> input;
unsigned long ul = input.to_ulong();
Remplacer:
if((mask&a) >= 1)
soit:
if ((mask & a) != 0)
ou:
if (mask & a)
Votre problème est que le dernier bit vous donne un nombre négatif, pas positif.
Le problème avec 1 << = 31 a été abordé dans un autre commentaire. En ce qui concerne le code pour la conversion chaîne -> int, vous avez plusieurs options:
ou si vous voulez vraiment implémenter la conversion vous-même, essayez le code suivant:
int BinaryStringToDecimal(string a)
{
int Rslt = 0;
int Mask = 1;
for (int i = a.length()-1; i >= 0; --i, Mask <<= 1) {
if (a.at(i) != '0') {
Rslt |= Mask;
}
}
return (Rslt);
}
Notez que ce code traite différemment les nombres négatifs par rapport à votre code: dans votre fonction, le bit de poids fort est pris en tant que signum. Si le bit le plus à gauche dans l'argument de chaîne de votre fonction n'est pas à la position 32 (en comptant à partir de la droite), votre fonction peut générer des résultats incorrects. Dans le code suggéré ici, il n’existe pas de traitement spécial du signum. Mais si vous obtenez la chaîne de 32 chiffres avec "1" comme le plus à gauche, le MSB dans int résultat sera == 1 et le nombre entier sera négatif (comme il se doit)
J'ai vérifié votre code et n'ai trouvé aucune erreur. Voici le code que j'ai utilisé ...
#include <iostream>
#include <string>
using namespace std;
int main ()
{
int a=1111165117;
string binary ("");
int mask = 1;
for(int i = 0; i < 31; i++)
{
if((mask&a) >= 1)
binary = "1"+binary;
else
binary = "0"+binary;
mask<<=1;
}
cout<<binary<<endl;
system("PAUSE"); //optional if not using ideone
return EXIT_SUCCESS; //optional if not using ideone
}
La sortie sera 10011100010101110101111010011101 . Si vous pouvez l'exécuter sur ideone
Et pourquoi ne pouvez-vous pas simplement convertir int
en uint
? Il est alors très facile de générer la chaîne binaire car vous n’aurez pas à vous soucier du bit de signe. Il en va de même pour la conversion d'une chaîne binaire en int
: le construit en tant que uint
, puis le transforme en int
:
string DecimalToBinaryString(int a)
{
uint b = (uint)a;
string binary = "";
uint mask = 0x80000000u;
while (mask > 0)
{
binary += ((b & mask) == 0) ? '0' : '1';
mask >>= 1;
}
cout<<binary<<endl;
return binary;
}
Et, bien sûr, vous pouvez appliquer les optimisations mentionnées, comme pré-allouer le tampon de chaîne, etc.
Aller dans l'autre sens:
uint b = 0;
for (int i = 31; i >=0; --i)
{
b <<= 1;
if (a.at(i) == '1')
b |= 1;
}
int num = (int)b;