Astuces de recherche...
Home
- Accueil & nouveautés
- Les newsgroups VB
- Téléchargements
- L'équipe
- Nous contacter
- Liens
Rubriques
- Toutes les questions
- Affichage & graphismes
- Algorithmique
- API
- Base de registre
- Bases de données
- Contrôles
- Date & heure
- Déploiement
- Divers
- Erreurs & problèmes
- Fichiers & dossiers
- Généralités
- Impression
- Internet & mails
- Math
- Multimédia
- Réseaux
- Structures de données
- Texte & strings
- VB .Net
- VB Script
- VBA
- Windows

Question 89

Comment convertir la représentation d'un nombre d'une base vers une autre ?

Dans la vie courante, les nombres sont généralement représentés par une suite de chiffres pouvant aller de 0 à 9, chaque chiffre possédant un poids différent en fonction de sa position. Ces poids sont en fait les puissances décroissantes de la base, dans ce cas-ci 10, le dernier chiffre étant affecté d'un poids 1 (100). On parle donc d'une numérotation de position en base 10. Ainsi 52610 représente :

(5 * 102) + (2 * 101) + (6 * 100)
ou encore
500 + 20 + 6

La numérotation de position n'est pas la seule manière de représenter des nombres. Par exemple, la numérotation romaine utilise des lettres d'un poids fixe et effectue leur somme (ou leur différence) ; ainsi 1830 sera représenté par :

MDCCCXXX
ce qui équivaut à :
1000 + 500 + 100 + 100 + 100 + 10 + 10 + 10

Ce type de représentation présente deux gros défauts : d'une part il ne permet pas de représenter facilement de grands nombres et d'autre part il ne permet pas d'effectuer simplement les opérations arithmétiques habituelles.

De manière générale, une numérotation de position en base B utilise des chiffres pouvant aller de 0 à B - 1. Ceux-ci étant affecté d'un poids décroissant Bi, le dernier étant toujours égal à 1 (B0).

Exemples :

1235 = (1 * 52) + (2 * 51) + (3 * 50) = 25 + 10 + 3 = 3810

1238 = (1 * 82) + (2 * 81) + (3 * 80) = 64 + 16 + 3 = 8310

101102 = (1 * 24) + (0 * 23) + (1 * 22) + (1 * 21) + (0*20) = 16 + 0 + 4 + 2 + 0 = 2210

La notation hexadécimale, désignant en fait une représentation en base 16, nécessite 16 chiffres. Or il n'en existe que 10 (0, 1, 2, ... , 9) ! Pour pallier à ce problème, on a donc décidé d'employer les lettres A, B, C, D, E et F pour représenter respectivement 10, 11, 12, 13, 14 et 15. Exemple :

A15F = (A * 163) + (1 * 162) + (5 * 161) + (F * 160) = (10 * 163) + (1 * 162) + (5 * 161) + (15 * 160) = 40960 + 256 + 80 + 15 = 4131110

L'emploi combiné de lettres et de chiffres permet donc de représenter des nombres dont la base est (strictement) inférieure à 36 (10 chiffres + 26 lettres). Imaginons maintenant que l'on ait une base supérieure ou égale à 36. Un exemple d'une telle base est la notation RGB qui peut-être assimilée à une représentation en base 256. Dans ce cas, on utilise la notation décimale pour représenter chaque composante du nombre, celles-ci étant séparées par un délimiteur (comme par exemple le point). Exemple :

0.170.253255 = (0 * 2562) + (170 * 2561) + (253 * 2560) =  0 + 43520 + 253 = 43773 = RGB(253, 170, 0) = 00AAFD16

Notez que la notation RGB est inversée, le poids des composantes étant croissant.

Remarquez aussi que l'on peut faire facilement un lien entre la notation hexadécimale et la représentation en base 256. En effet, si l'on décompose 00AAFD16 en paquets de deux, on obtient 0016 = 0, AA16 = 170 et FD16 = 253. Cela tient au fait que 256 est une puissance de 16 (en effet 162 = 256).

Voyons maintenant comment passer d'une représentation en base 10 à une représentation en une autre base B. Il faut partir de la constatation que les chiffres de la représentation sont fournis par la suite (inversée) des restes des divisions successives par B. Un exemple nous aidera à y voir plus clair :

Calculons la représentation binaire de 2210 :

22 / 2 = 11, reste 0
11 / 2 = 5, reste 1
5 / 2 = 2, reste 1
2 / 2 = 1, reste 0
1 / 2 = 0, reste 1
On obtient donc : 101102

Autre exemple : Calculons la représentation hexadécimale de 1068034810 :

10680348 / 16 = 667521, reste 12
667521 / 16 = 41720, reste 1
41720 / 16 = 2607, reste 8
2607 / 16 = 162, reste 15
162 / 16 = 10, reste 2
10 / 16 = 0, reste 10
On obtient donc : 10.2.15.8.1.1216 = A2F81C16

Il ne reste maintenant plus qu'à traduire tout cela en code Visual Basic afin de se créer une fonction de conversion universelle :

Option Explicit

Public Function DecimalToBase(ByVal nNumber As Long, ByVal DstBase As Long) As String

    Do While (nNumber >= DstBase)
        DecimalToBase = NumberToSymbol((nNumber Mod DstBase), DstBase) & DecimalToBase
        If DstBase >= 36 Then DecimalToBase = "." & DecimalToBase
        nNumber = nNumber \ DstBase
    Loop
    DecimalToBase = NumberToSymbol(nNumber, DstBase) & DecimalToBase

End Function

Public Function NumberToSymbol(ByVal nNumber As Long, ByVal DestBase As Long) As String

    If ((nNumber >= 10) And (nNumber < 36) And DestBase < 36) Then
        NumberToSymbol = Chr(Asc("A") + (nNumber - 10))
    Else
        NumberToSymbol = nNumber
    End If

End Function

Public Function BaseToDecimal(ByVal sNumber As String, ByVal SrcBase As Long) As Long

    Dim i As Integer
    Dim v() As String

    If SrcBase < 36 Then
        For i = 0 To Len(sNumber) - 1
            BaseToDecimal = BaseToDecimal + SymbolToNumber(Mid(sNumber, Len(sNumber) - i, 1)) * (SrcBase ^ i)
        Next
    Else
        v() = Split(sNumber, ".")
        For i = 0 To UBound(v)
            BaseToDecimal = BaseToDecimal + SymbolToNumber(v(UBound(v) - i)) * (SrcBase ^ i)
        Next
    End If

End Function

Public Function SymbolToNumber(ByVal sSymbol As String) As Long

    If Len(sSymbol) = 1 And Asc(UCase(sSymbol)) >= Asc("A") And Asc(UCase(sSymbol)) <= Asc("Z") Then
        SymbolToNumber = (Asc(UCase(sSymbol)) - Asc("A")) + 10
    Else
        SymbolToNumber = CLng(sSymbol)
    End If

End Function

Public Function BaseToBase(ByVal vNumber As Variant, ByVal SrcBase As Long, ByVal DstBase As Long) As Variant

    Dim nDecTemp As Long

    If (SrcBase <> 10) Then
        nDecTemp = BaseToDecimal(vNumber, SrcBase)
    Else
        nDecTemp = vNumber
    End If

    If (DstBase <> 10) Then
        BaseToBase = DecimalToBase(nDecTemp, DstBase)
    Else
        BaseToBase = nDecTemp
    End If

End Function

Private Sub Form_Load()

    MsgBox BaseToBase("101010101", 2, 16)
    MsgBox BaseToBase("AEF09", 16, 10)
    MsgBox BaseToBase("255.126.0", 256, 10)

End Sub

La fonction DecimalToBase permet de convertir une représentation décimale en n'importe quelle base ; inversément, la fonction BaseToDecimal permet de convertir n'importe quelle représentation en représentation décimale. Notons que si la base est supérieure ou égale à 36, des nombres décimaux sont utilisés pour représenter les différentes composantes, ceux-ci étant séparés par un point.

La fonction NumberToSymbol permet à partir d'un nombre donné, d'en trouver son symbole. Exemple 10 devient A, 11 devient B, etc... SymbolToNumber étant la fonction inverse.

La fonction BaseToBase permet, quant à elle, de convertir la représentation d'un nombre d'une base quelconque vers une autre base quelconque par le biais des fonctions DecimalToBase  et BaseToDecimal.

Date de publication : 16 septembre 2002
Dernière modification : 05 janvier 2003
Rubriques : Math
Mots-clés : convertir, conversion, décimal, binaire, hexadécimal, base, nombres, représentations