Partage

Algorithme de conversion de binaire vers base 10.

Je sais, on va m'engueuler mais j'ai pas trouvé ...

Sujet résolu
Le 19 décembre 2009 à 13:02:51

Bonjour !

Dans le besoin d'un convertisseur rapide de binaire vers décimal, je me tourne vers vous : comment convertir un nombre binaire en nombre décimal par le biais d'un programme ?
J'ai cherché sur le forum et sur le Web mais les seules choses que j'ai trouvé c'est des conversions de décimal vers binaire ou des conversions qui ne marchent pas.
Quelle est la formule ?

PS : voilà le début du code ...
int i = 10; // i = 2 en mode non-binaire

Merci ! ;)
Publicité
Le 19 décembre 2009 à 13:02:51
Le 19 décembre 2009 à 13:09:34

salut, c'est au programme de 1er donc voila
2 solution ->

1) tu code chaque chiffre comme une valeur hexa et tu les met a la chaine
2) tu prend un tableau des valeur binaire ronde (1, 2, 4, 8, 16 ...) et tu addition les valeur a 1
par exemple pour 0101 sa fait 0*8 + 1*4 + 0*2 + 1*1 donc 5

... j'explique trop mal o_O
Le 19 décembre 2009 à 13:12:12

C'est pas très classe ce que tu nous fais... un int, c'est un nombre qui a une valeur, quelle que soit sa base... La, ton int vaut 10, 0xA, tout ce que tu veux mais certainement pas 2. Tu veux peut-être faire ça au niveau de chaines de caractère. Dans ce cas, c'est simple.
std::string a("1001");
int value = 0;
for(int i = a.length() - 1; i > -1 ; i--)
{
     value += pow(i, 2) * ((a[i] == '1') ? 1 : 0);
}

Je ne sais pas si c'est correct mais c'est ce qui me vient en tête...
Le 19 décembre 2009 à 13:15:19

1001101 (base 2)

1*2^6 + 0*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0
= 64 + 0 + 0 + 8 + 4 + 0 + 1
= 77 (base 10)
Le 19 décembre 2009 à 13:21:52

gan_> Ok, c'est bien pour convertir dec vers bin mais après pour l'inverse ...

Naj> Donc ce code :
#include <iostream>
#include <cmath>

int main(int argc, char * argv[])
{
std::string s("10");
std::string finally("");
int val = 0;

for(unsigned int ui = 0; ui < s.size(); ui++)
{
val = pow(ui, 2) * ((s[ui] == '1') ? 1 : 0);
finally += val;
}

std::cout << finally << std::endl;
std::cin.ignore();
}

Afficherait bien la chaîne 2 ?

EDIT : converting to int from double.

Chlab_lak> Ah ok. Je test aussi ;)
Le 19 décembre 2009 à 13:31:39

Citation : Shydow

gan_> Ok, c'est bien pour convertir dec vers bin mais après pour l'inverse ...


o_O
j'explique pour aller du bien vers dec (même méthode que Chlab_lak)
Le 19 décembre 2009 à 13:39:26

gan_> Ok, mais tu as édité ton message pendant que je postais ^^"
Zéro d'honneur Le 19 décembre 2009 à 13:47:21

Il faut que tu comprenne que base 2 et base 10 ne sont que des représentations textuelles. Un nombre est quant à lui un nombre et il n'est au fond dans aucune base quand la machine le manipule -- il est juste au format compris par la machine. C'est tout.


Pour l'algo, il n'y a pas de secret..
- nombre vers chaine (quelle que soit la base) -> division successives.
- chaine (quelle que soit la base) vers nombre -> méthode de horner


PS: oubliez pow, cette approche n'est pas du tout efficace.

Bon je n'ai pas réussi a retrouver un seul endroit de la demi-douzaine où j'avais posté le code, donc le revoilà:
#include <string>
#include <iostream>
#include <stdexcept>
#include <vector>
#include <iterator>


template <typename E>
struct digits_trait {};

template <> struct digits_trait<char> {
    char operator[](char i) const {
	return "0123456789abcdefghijklmnopqrstuvwxyz"[i];
    }
};

template <> struct digits_trait<wchar_t> {
    wchar_t operator[](char i) const {
	return L"0123456789abcdefghijklmnopqrstuvwxyz"[i];
    }
};

template <typename E, typename N>
std::basic_string<E> number2base(N n, int base) {
    // const E digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    digits_trait<E> digits;
    std::basic_string<E> result;
    // result.reserve(operation_savante_à_base_de_logarithme(n));
    while (n) {
        N digit = n % base;
        n /= base;
        result += digits[digit];
    }
    return std::basic_string<E>(result.rbegin(), result.rend());
}

int digitValue(char digit) {
    if (digit >= 'a' && digit <='z') {
	return digit - 'a' + 10;
    } else if (digit >= 'A' && digit <='Z') {
	return digit - 'A' + 10;
    } else if (digit >= '0' && digit <='9') {
	return digit - '0';
    } else {
	throw std::runtime_error("Invalid digit");
    }
}

unsigned long base2number(std::string const& str, int base)
{
    unsigned long result = 0;
    for (std::string::const_iterator b = str.begin(), e = str.end()
	    ; b != e
	    ; ++b
	)
    {
	// std::cout << "r <- " << base << "*" << result << "+" << *b << "(" << digitValue(*b) << ")\n";
	result = base * result + digitValue(*b);
    }
    return result;
}

typedef std::vector<unsigned char> DigitsVector;
DigitsVector toTab(unsigned int n, unsigned int base=10)
{
    DigitsVector res;
    // éventuellement res.reserve(opération savante à base de log_{base}(n));
    do {
       res . push_back(n%base);
    } while (n /= base) ;
    return DigitsVector(res.rbegin(), res.rend());
}


int main (int argc, char **argv)
{
    int n;
    // std::cout << base2number("ff", 16);
    // return 0;
    std::cout << "n :";
    while (std::cin >> n) {
	const std::string v2 = number2base<char>(n,2);
	const std::string v8 = number2base<char>(n,8);
	const std::string v16 = number2base<char>(n,16);
	const DigitsVector  v = toTab(n);
	std::cout 
	    << "   -- 2: " << v2 << "(" << base2number(v2,2) << ")"
	    << "   -- 8: o" << v8 << "(" << base2number(v8,8) << ")"
	    << "   -- 16: 0x" << v16 << "(" << base2number(v16,16) << ")"
	    << "   -- ";
	std::copy(v.begin(),v.end(), std::ostream_iterator<int>(std::cout, " "));
	std::cout
	    << std::endl;
    }

    return 0;
}
Le 19 décembre 2009 à 13:54:17

ou tout simplement :
#include <iostream>
#include <cmath>

int main(int argc, char * argv[])
{
   std::string s("10");
   int val = 0;
   int i = 1;
   for(unsigned int ui = 0; ui < s.size(); ui++)
   {
         val += (s[ui] == '1') * i;
         i = i * 2;
   }
}
Le 19 décembre 2009 à 13:56:30

gan_> ISO C++ forbids comparison between pointer and integer
'1' et pas "1"
Le 19 décembre 2009 à 13:58:13

Citation : Shydow

gan_> ISO C++ forbids comparison between pointer and integer
'1' et pas "1"


exact ! :D
c'est l'habitude des QString :(

[edit] sinon, sa marche ?
Le 19 décembre 2009 à 13:59:26

En plus
#include <iostream>
#include <cmath>

int main(int argc, char * argv[])
{
std::string s("10");
int val = 0;
int i = 1;

   for(unsigned int ui = 0; ui < s.size(); ui++)
   {
      if (s[ui] == '1')
         val += 1 * i;
      i = i * 2;
   }
   
   std::cout << i;
   std::cin.ignore();
}
// ton code avec le cout et la pause en plus


Affiche 4 et pas 2 ^^"
Le 19 décembre 2009 à 14:00:51

Citation : Shydow

En plus

#include <iostream>
#include <cmath>

int main(int argc, char * argv[])
{
std::string s("10");
int val = 0;
int i = 1;

   for(unsigned int ui = 0; ui < s.size(); ui++)
   {
      if (s[ui] == '1')
         val += 1 * i;
      i = i * 2;
   }
   
   std::cout << i;
   std::cin.ignore();
}
// ton code avec le cout et la pause en plus



Affiche 4 et pas 2 ^^"



si tu n'affiche pas la bonne variable c'est normal :)
il faut prendre val en sortie, pas i :lol:
Le 19 décembre 2009 à 14:09:37

Confusion de ma part ^^"

Il marche pas quand la chaine finit par 1 mais pas quand elle finit par zéro : dans ce cas, val est toujours égal à 1 ...
Le 19 décembre 2009 à 14:26:56

normal, il faut prendre la chaine a l'envers
for(unsigned int ui = 0; ui < s.size(); ui++)
	{
		if (s[s.size() - ui - 1] == '1')
		{
			val = val + i;
		}
		i = i * 2;
	}

Le 19 décembre 2009 à 18:51:25

Ou commencer le compte à l'envers ^^"
Zéro d'honneur Le 19 décembre 2009 à 19:07:23

Là ça va (si on excepte que tout ce qui n'est pas '1' est traité comme un '0') parce que vous bossez sur des entiers, mais cette approche souffre de problèmes d'approximations avec des réels. D'où Horner...
Le 19 décembre 2009 à 21:03:39

Je viens de jeter un coup d'oeil sur la méthode d'Horner, même si je n'ai pas tout compris, sa vitesse doit être effarante par rapport à un algorithme naïf, vu qu'elle n'a a calculer aucun carré sur une conversion d'une base à une autre !
Le 19 décembre 2009 à 21:07:38

Citation : Gigotdarnaud

Je viens de jeter un coup d'oeil sur la méthode d'Horner, même si je n'ai pas tout compris, sa vitesse doit être effarante par rapport à un algorithme naïf, vu qu'elle n'a a calculer aucun carré sur une conversion d'une base à une autre !


ma methode n'utilise aucun carré o_O
Le 19 décembre 2009 à 22:38:26

JE voudrais pas dire, mais il existe la fonction strtol dans la bibliothèque C...
Le 20 décembre 2009 à 8:34:53

Citation : QuentinC 2

JE voudrais pas dire, mais il existe la fonction strtol dans la bibliothèque C...


...?
On parle de binaire vers décimal pas de const char* vers long là o_O
Le 20 décembre 2009 à 10:00:17

Citation

On parle de binaire vers décimal pas de const char* vers long là


Ben oui, justement : strtol prend une chaîne représentant un nombre dans une base quelconque, donc tu peux convertir une chaîne représentant un nombre binaire.
Le 20 décembre 2009 à 10:29:10

Pour passer d'une base 2 à une base 10, on peut faire ça :

On stocke le nombre binaire dans un string.

On lit chaque caractères de string.
Pour chaque membre du vector, on multplie par 2.
On rajoute 0 si le caractère est '0', sinon on rajoute 1 -> dans le vector

On fait la somme de tous les éléments du vector
Et on l'affiche.

#include <iostream> // std::cout, std::cin
#include <string> // std::string
#include <vector> // std::vector
#include <algorithm> // for_each()

typedef unsigned long long int ulli; // Pour eviter des types super longs

inline void foisDeux (ulli &nbr) {
     nbr *= 2;
}

int main (void) {
    std::vector <ulli> decimal(0,0);
    std::string binaire;
    ulli somme = 0; //Va contenir le nombre decimal (somme des elements du vector
                    //"decimal")

    std::cin >> binaire;

    for (unsigned i = 0; i < binaire.length(); i++) {
        for_each (decimal.begin(), decimal.end(), foisDeux);
        decimal.push_back ( (ulli) (binaire[i] == '0') ? 0 : 1 );
    }

    for (unsigned i = 0; i < decimal.size(); i++)
        somme += decimal[i];

    std::cout << somme;

    getchar();

    return EXIT_SUCCESS;

}
Le 20 décembre 2009 à 10:33:47

QuentinC 2> Ah ok ^^

Je cherchais surtout un algorithme mais c'est pas grave, j'ai trouvé les deux ^^

Algo-rythme> Je testerai également ;)

Merci à tous ! -résolu-
Zéro d'honneur Le 20 décembre 2009 à 13:26:56

Citation : Shydow

On parle de binaire vers décimal pas de const char* vers long là o_O


binaire, décimal, octal, hexadécimal, ... ne sont que des représentations textuelles de nombres.
Le 22 décembre 2009 à 21:22:06


Naj> Donc ce code :
#include <iostream>
#include <cmath>

int main(int argc, char * argv[])
{
std::string s("10");
std::string finally("");
int val = 0;

for(unsigned int ui = 0; ui < s.size(); ui++)
{
val = pow(ui, 2) * ((s[ui] == '1') ? 1 : 0);
finally += val;
}

std::cout << finally << std::endl;
std::cin.ignore();
}

Afficherait bien la chaîne 2 ?</citation>
Euh... Je pense même pas qu'il compilera... Ajouter un int à un string, c'est bizarre, non ?
Le 22 décembre 2009 à 21:33:24

Je suis pas expert en C++ mais vous ne vous compliquez pas un peu la vie là ? ^^

#include <iostream>
#include <string>

int main(void) {
	std::string s("11001");
	int val = 0;
	
	for (int i = 0; i < s.size(); i++) {
		val <<= 1;
		val ^= (s[i] == '0') ? 0 : 1;
	}
	std::cout << val;
	return 0;
}
Le 22 décembre 2009 à 21:50:22

Juste pour t'embêter, le void n'est pas obligatoire en C++ et donc, inutile de s'encombrer avec des mots en plus dans le code, de plus comme tu n'utilises pas l'espace de nommage, ce serait plutôt std::cout et il faut inclure string :p

Mais en effet, je crois que c'est le plus simple.
Le 22 décembre 2009 à 21:52:42

Ah le void n'est pas obligatoire :D
Pour le string il était inclus plus haut dans mon code et j'avais utilisé using namespace :-°
J'édite ^^
Le 22 décembre 2009 à 22:01:05

(Attention, je n'apporte absolument rien de nouveau au topic)

std::string bin("11001");
int dec = 0;

for(int t = 1, i = bin.size()-1; i >= 0; t *= 2)
   dec += (bin[i--]-'0') * t;

std::cout << dec; // 25

Algorithme de conversion de binaire vers base 10.

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown