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. |