L'électronique produit le format numérique le plus simple dans la mesure ou seuls un niveau "bas" et un niveau "haut" peuvent exister sur une ligne logique (Je fais volontairement abstraction du niveau "ouvert", qui n'a aucune incidence dans cette explication). En utilisant parallèlement plusieurs lignes logiques, il est possible d'étendre la plage de valeurs produites. Ceci est possible en affectant un "poids" à chaque ligne logique. Le tableau ci-dessous illustre comment il est possible de générer des valeurs comprises entre 0 et 7 (8 pas) en utilisant 3 lignes logiques
| Poids | |||
| 4 | 2 | 1 | Valeurs résultantes |
| 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 0 | 2 |
| 0 | 1 | 1 | 3 |
| 1 | 0 | 0 | 4 |
| 1 | 0 | 1 | 5 |
| 1 | 1 | 0 | 6 |
| 1 | 1 | 1 | 7 |
Exemple: La valeur résultante 5 est le résultat de: 1 x 1 + 0 x 2 + 1 x 4 = 1 + 0 + 4 = 5. Le premier terme de chaque produit est la valeur du niveau logique, le second terme est son poids.
De cette démonstration, il est possible d'extrapoler les valeurs qu'il est possible d'atteindre avec 4, 8, 16 et 32 lignes (on parle de bits) et plus
| Mini | Maxi | |||
| Bits | Décimal | Binaire | Décimal | Binaire |
| 4 | 0 | 0000 | 15 | 1111 |
| 8 | 0 | 0000 0000 | 255 | 1111 1111 |
| 16 | 0 | 0000 0000 0000 0000 | 65535 | 1111 1111 1111 1111 |
| 32 | 0 | 0000 0000 0000 0000 0000 0000 0000 0000 | 4294967295 | 1111 1111 1111 1111 1111 1111 1111 1111 |
Nota: Convertir de grandes valeurs binaires en décimal est un peu fastidieux; vous pouvez utiliser le convertisseur de la Calculatrice disponible dans l'environnement Windows (en mode Scientifique).
VB: VB offre un type de variable pour les variables booléennes (1 bit pouvant prendre les valeurs 0 ou 1), il s'agit du format "Boolean". Notez que malgré les apparences, ce format consomme 16bits!
Conversions (par l'exemple)
Entier en binaire
La méthode classique des restes:
Public Function Integer2Binary( _
ByVal Value As Long) As String
Dim BitsString As String
Dim Remainder As Integer
Do While Value 0
'compute remainder
Remainder = Value Mod 2
'upadte value
Value = Value \ 2
'format result
BitsString = Format(Remainder) & BitsString
Loop
'format result
If BitsString = "" Then
BitsString = "0"
End If
'returned value
Integer2Binary = BitsString
End Function
Variante:
Public Function Integer2BinaryPwrMethod( _
ByVal Value As Long, _
Optional ByVal NbrBits As Long = 8) As String
Dim BitIndex As Integer
Dim BitsString As String
Dim BitValue As Integer
For BitIndex = NbrBits To 1 Step -1
'compare values sign
If Value >= 2 ^ (BitIndex - 1) Then
'upadte value
Value = Value - 2 ^ (BitIndex - 1)
BitValue = 1
Else
BitValue = 0
End If
'format result
BitsString = BitsString & Format(BitValue)
Next
'returned value
Integer2BinaryPwrMethod = BitsString
End Function
Binaire en entier
Public Function Binary2Integer( _
ByVal BinaryValue As String) As Long
Dim BitIndex As Integer
Dim BitValue As Integer
Dim IntegerValue As Long
For BitIndex = 1 To Len(BinaryValue)
BitValue = Val(Mid(BinaryValue, BitIndex, 1))
IntegerValue = IntegerValue + BitValue * 2 ^ (Len(BinaryValue) - BitIndex)
Next
'returned intefer value
Binary2Integer = IntegerValue
End Function
Jusque là, tout va bien, au détail près que les ces valeurs entières sont toutes positives. Il va donc falloir utiliser un artifice pour "signer" les valeurs décimales à l'aide d'un codage binaire spécifique. Deux options sont possibles: complément par 1 et complément par 2
L'algèbre de Bool (du nom de son inventeur), régit les opérations qu'il est possible d'effectuer sur codes valeurs binaires. Ces opérations sont généralement présentées sous forme de tableaux à plusieurs colonnes. La ou les premières colonnes contiennent les valeurs que peuvent prendre un ou plusieurs bits (les variables), la dernière colonne contient le résultat attendu pour l'opération. Ces tables portent là encore de le nom de leur inventeur: Karnaugh
Fonction Not
| b0 | Not |
| 0 | 1 |
| 1 | 0 |
Fonction Or
| b1 | b0 | Or |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
Application: l'exemple ci dessous utilise la fonction Or pour attribuer la valeur 1 à un bit particulier d'une valeur binaire
Function BitSet( _
ByVal Value As Long, _
ByVal BitIndex As Integer) As Long
'apply OR to the bit mask
BitSet = (Value Or 2 ^ (BitIndex - 1))
End Function
Fonction Nor (Not or)
| b1 | b0 | Nor |
| 0 | 0 | 1 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 0 |
Fonction Xor (Or exclusif: ou l'un ou l'autre, mais pas les deux!)
| b1 | b0 | Xor |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
Application: l'exemple ci dessous utilise les fonctions Xor pour inverser la valeur d'un bit particulier d'une valeur binaire
End Function
Function BitToggle( _
ByVal Value As Long, _
ByVal BitIndex As Integer) As Long
'apply XOR with the negation to the bit mask
BitToggle = (Value Xor 2 ^ (BitIndex - 1))
End Function
Fonction And
| b1 | b0 | And |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
Application: l'exemple ci dessous utilise les fonctions And and Not pour attribuer la valeur 0 à un bit particulier d'une valeur binaire
Function BitClear( _
ByVal Value As Long, _
ByVal BitIndex As Integer) As Long
'apply AND with the negation to the bit mask
BitClear = (Value And Not 2 ^ (BitIndex - 1))
End Function
Application: l'exemple ci dessous utilise les fonctions And pour lire la valeur d'un bit particulier d'une valeur binaire
Function BitStatus( _
ByVal Value As Long, _
ByVal BitIndex As Integer) As Boolean
'apply AND to the bit mask
BitStatus = Value And 2 ^ (BitIndex - 1)
Fonction Nand (Not And)
| b1 | b0 | Nand |
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
Signe et magnitude
C'est la méthode la plus simple; elle consiste à réserver un bit pour le signe et à utiliser les autres bits pour définir la grandeur de la valeur numérique
Exemples: Le tableau ci-dessous exprime les valeurs 0 et 5 en positif et négatif
|
Poids |
|||||
| Signe | 4 | 2 | 1 | Binaire | Décimal |
| 0 | 1 | 0 | 1 | 0101 | +5 |
| 0 | 0 | 0 | 0 | 0000 | (+) 0 |
| 1 | 0 | 0 | 0 | 1000 | (-) 0 |
| 1 | 1 | 0 | 1 | 1101 | -5 |
L'observation du tableau montre qu'il existe deux manière de représenter la valeur 0, ce qui pose quelques problèmes au niveau des processeurs pour l'exécution d'opérations binaires (ex: addition). Aussi ce mode de représentation est très peu usité
Complément par 1
Cette méthode est utilisée par certains types de processeurs. Elle consiste très simplement à inverser les bits de la valeur binaire de la valeur entière positive. De même que dans le cas des valeurs exprimées en format "signe et magnitude", le premier bit est réservé au signe.
Exemples: Le tableau ci-dessous exprime les valeurs 0 et 5 en positif et négatif
|
Poids |
|||||
| Signe | 4 | 2 | 1 | Binaire | Décimal |
| 0 | 1 | 0 | 1 | 0101 | +5 |
| 0 | 0 | 0 | 0 | 0000 | (+) 0 |
| 1 | 1 | 1 | 1 | 1111 | (-) 0 |
| 1 | 0 | 1 | 0 | 1010 | -5 |
L'observation du tableau montre qu'il existe deux manière de représenter la valeur 0, ce qui pose quelques problèmes au niveau des processeurs pour l'exécution d'opérations binaires (ex: addition). Aussi ce mode de représentation est très peu usité
Complément par 2
C'est la méthode est un peu plus compliquée, mais elle présente l'avantage de ne proposer qu'un seul format pour la valeur 0, et de retourner une valeur 0 lors de l'exécution de l'opération binaire -x + x = 0. La méthode est la suivante:
Exemples: Créer la valeur -13 sous 8 bits
Convertir la valeur absolue décimale en binaire
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 00001101 | 13 |
Inverser tous les bits
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 11110010 | (242) |
Ajouter 1
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 | 11110010 | (242) |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 00000001 | 1 |
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 11110010 | -13 (243) |
-13 converti en binaire signé égale donc 11110010
La conversion inverse s'effectue en appliquant la méthode suivante:
Retenir la valeur du premier bit
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 11110010 | -13 (243) |
1= signe négatif
Inverser tous les bits
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 11110010 | -13 (243) |
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 00001100 | 12 |
Ajouter 1
|
Poids |
|||||||||
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | Binaire | Décimal |
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 00001100 | 12 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 00000001 | +1 |
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 00001101 | 13 |
Par ailleurs, on vérifie que -13 + 13 =0
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | Retenue | ||
| 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 11110010 | -13 (243) |
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 00001101 | 13 |
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00000000 | résultat |
VB: VB offre différents types de variables qui appliquent les règles précédemment expliques
| Nom du format | Nombre de bits | Mini | Maxi |
| "Integer" | 16 | -32,768 | 32,767 |
| "Long" | 32 | -2147483648 | 2147483647 |
Nous avons vu comment exprimer des valeurs entières signés ou non dans une plage de valeurs dépendant du nombre de bits utilisés. Cependant, ces formats présentent deux inconvénients: il ne permettent pas l'expression de valeurs fractionnaires et la plage de valeurs décimales équivalente est réduite. C'est la raison pour laquelle les formats en Virgule Flottante ont été mis au point. Il s'agit ni plus ni moins que du format scientifique appliqué au binaire.
Le principe est relativement simple: chaque valeur numérique est représentée sous la forme d'une mantisse (normalisée et signée) et d'un exposant (signé). La mantisse est elle même constituée d'une somme de fractions; chaque fraction est l'inverse de 2 élevé à la puissance correspondant au poids du bit. Exemple le premier bit de mantisse exprimera la valeur 1 / 2^1 soit un demi, le bit suivant exprimera la valeur 1 / 2^2 soit un quart et ainsi de suite. Et pourquoi ne démarre t'on pas à 1 / 2^0? Tout simplement parce que 1 / 2^0 = 1 et que 1 est l'élément neutre des produits et donc inutile et superflu dans l'expression de la mantisse! Autre question: comment définir un exposant négatif? Très simple, la valeur binaire est décalée de la moitié de sa plus grande valeur. Si l'exposant utilise 4 bits, le décalage est donc de (2^3)-1 soit 7
L'exemple de représentation de valeurs décimales en formats virgule flottante; le nombre de bits est volontairement réduit pour faciliter la compréhension: 1 bit de signe, 4 bits d'exposant et 3 bits de mantisse
| Bit de signe | Bits d'exposant | Bit de mantisse | Valeur décimale | |||||
| 1==+ | 8 | 4 | 2 | 1 | 4 | 2 | 1 | |
| 1 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | -1.5 |
VB: VB offre différents types de variables, compatibles avec la norme IEEE 754 qui appliquent les règles précédemment expliquées
| Nom du format | Nombre de bits | Mini négatif | Maxi négatif | Mini positif | Maxi positif |
| "Single" | 32 | -3.402823e38 | -1.401298e-45 | 1.401298e-45 | 3.402823e38 |
| "Double" | 64 | -1.79769313486232e308 | -4.94065645841247e-324 | 4.94065645841247e-324 | 1.79769313486232e308 |
Représentation du format IEEE 754 32 bits
| Bit de signe | Bits d'exposant | Bits de mantisse | |||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
Conversions (par l'exemple)
Fractionnaire en binaire
Public Function Fractional2Binary( _
ByVal Value As Double, _
Optional ByVal NumberDecimalPlaces As Integer = 16) As String
Dim BitsString As String
Dim IntegerValue As Integer
Dim NumberBits As Integer
Do While Value 0
'compute twice the Value
Value = Value * 2
'compute integer
IntegerValue = Int(Value)
'retain fractional value
Value = Value - IntegerValue
'format result
BitsString = BitsString & Format(IntegerValue)
'Number of bits limitation (avoid infinite looping)
NumberBits = NumberBits + 1
If NumberBits >= NumberDecimalPlaces Then
Exit Do
End If
Loop
'returned value
Fractional2Binary = BitsString
End Function
Binaire en fractionnaire
Public Function Binary2Fractional( _
ByVal BinaryValue As String) As Double
Dim BitIndex As Integer
Dim BitValue As Integer
Dim FractionalValue As Double
'trim separator
BinaryValue = Right(BinaryValue, Len(BinaryValue) - 1)
'compute fractional value
For BitIndex = 1 To Len(BinaryValue)
BitValue = Val(Mid(BinaryValue, BitIndex, 1))
FractionalValue = FractionalValue + BitValue / (2 ^ BitIndex)
Next
'returned value
Binary2Fractional = FractionalValue
End Function
Ayant procédé à la conversion de la valeur décimale (type eee.ffff) en valeur binaire (type bbb.bbb), il est maintenant nécessaire de normaliser la valeur sous la forme b.bbbbb ou b est fatalement égal à "1", et de noter la puissance (de 2) à laquelle il faut élever la valeur normaliser pour qu'elle soit toujours égale à sa valeur initiale (type bbb.bbb).
Cas spéciaux
Encore plus fort, le format IEEE 754 permet aussi la codification de valeurs spéciales. Le tableau ci-dessous récapitules ces cas pour le format sous sous 32 bits
| Signe | Exposant (e) | Fraction (f) | Valeur |
|---|---|---|---|
| 0 | 00..00 | 00..00 | +0 |
| 0 | 00..00 | 00..01 : 11..11 |
Réel Positif Dénormalisé 0.f x 2(-b+1) |
| 0 | 00..01 : 11..10 |
XX..XX | Réel Positif Normalisé 1.f x 2(e-b) |
| 0 | 11..11 | 00..00 | +Infini |
| 0 | 11..11 | 00..01 : 01..11 |
NaN |
| 0 | 11..11 | 10..00 : 11..11 |
NaN |
| 1 | 00..00 | 00..00 | -0 |
| 1 | 00..00 | 00..01 : 11..11 |
Réel Négatif Dénormalisé -0.f x 2(-b+1) |
| 1 | 00..01 : 11..10 |
XX..XX | Réel Négatif Normalisé -1.f x 2(e-b) |
| 1 | 11..11 | 00..00 | -Infini |
| 1 | 11..11 | 00..01 : 01..11 |
NaN |
| 1 | 11..11 | 10..00 : 11.11 |
NaN |
NaN=Not a Number
Le résultat des opérations portant sur des nombres en virgule flottante au format IEEE 754 correspond aux données du tableau ci-dessous
| Opération | Résultat |
|---|---|
| n / ±Infini | 0 |
| ±Infini x ±Infini | ±Infini |
| ±non zéro / 0 | ±Infini |
| Infini + Infini | Infini |
| ±0 / ±0 | NaN |
| Infini - Infini | NaN |
| ±Infini / ±Infini | NaN |
| ±Infini x 0 | NaN |
La totale
Les deux exemples de code ci-dessous permettent de convertir une valeur numérique décimale en une valeur hexadécimale (et vis versa) sous 32bits, 100% compatible avec le standard IEEE-754. Les trois premières lignes doivent être collées dans la partie déclaration du module
Public Const DCV_ERR_FLT_INF = 0
Public Const DCV_ERR_FLT_NAN_SIG = 1
Public Const DCV_ERR_FLT_NAN_QUI = 2
Décimal à hexadécimal
Public Function Decimal2HEX_IEEE754_dcv( _
ByVal Value As Double) As Variant
Dim Result As String
Dim Sign As Long
Dim Mantissa As Variant
Dim Exponent As Variant
Dim PoweredValue As Double
Dim Buffer As String
If Value = 0 Then
Sign = &H0
Exponent = &H0
Mantissa = &H0
Else
'get sign
If Value 1
If PoweredValue >= 2 Then
PoweredValue = PoweredValue / 2
Exponent = Exponent + 1
Else
PoweredValue = PoweredValue * 2
Exponent = Exponent - 1
End If
Loop
If Exponent >= -126 Then
'normalized value
'compute mantissa
Mantissa = (PoweredValue - 1) * &H800000
'compute exponent
Exponent = (127 + Exponent) * &H800000
Else
'de normalized value
'compute mantissa
Mantissa = Int(PoweredValue * 2 ^ (149 + Exponent))
'set exponent
Exponent = &H0
End If
End If
'concatenate strings
Result = "&H" & Hex(Sign + Exponent + Mantissa)
'returned value
Decimal2HEX_IEEE754_dcv = Result
End Function
Hexadécimal à décimal
Public Function HEX_IEEE7542Decimal_dcv( _
ByVal Value As Variant) As Variant
Dim Exponent As Long
Dim Mantissa As Long
Dim Sign As Integer
Dim SignBit As Boolean
Dim Result As Single
'apply bit mask to extract sign status
SignBit = Value And &H80000000
'compute sign
Sign = ((-1) ^ SignBit)
'apply bit mask to extract mantissa
Mantissa = (Value And &H7FFFFF)
'apply bit mask to extract exponent
Exponent = (Value And &H7F800000)
'shift bits 23 positions to the right
Exponent = Exponent \ &H800000
'compute result
If Exponent = 0 Then
If Mantissa = 0 Then
'whatever the sign
Result = 0
Else
'denormalized result
Result = Sign * Mantissa * 2 ^ -149
End If
ElseIf Exponent = &HFF Then
If Mantissa = 0 Then
'infinite
ErrorCode = DCV_ERR_FLT_INF
Exit Function
ElseIf Mantissa
Liens
Les formats numériques de VB passés au peigne fin
http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/
IEEE Standard 754
http://stevehollasch.com/cgindex/coding/ieeefloat.html
http://fred.just.free.fr/francais/index.php?from=http://fred.just.free.fr/francais/exemples/Ieee.html
http://www.trotek.ec-lyon.fr/~muller/cours/numeration/flp_ieee.html.fr
Opérations sur les valeurs binaires
http://www.evergreen.edu/biophysics/technotes/misc/bin_math.htm
http://www.evergreen.edu/biophysics/technotes/program/2s_comp.htm
http://www.fact-index.com/n/ne/negative_and_non_negative_numbers.html
http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/