6. Programmation et binaire
Il s'agit dans cette partie d'écrire et tester des fonctions qui agissent sur des entiers non signés.
Pour tester la fonction, on pourra utiliser une macro-instruction du C et des entiers 32 bits non signés en définissant le type u32 :
#include <cstdlib> // for uint32_t
#include <iostream>
//
// Définition d'un type entier 32 bits non signé
// appelé u32 pour Unsigned 32 bits
//
typedef uint32_t u32;
//
// Macro instruction qui compare le paramètre x à y.
// Normalement x correspond à la valeur issue d'un appel
// de fonction.
//
// L'utilisation de #x transforme le x sous forme d'une
// chaîne de caractères, ainsi #msb(0) devient "msb(0)".
//
// Si x est différent de y on affiche une erreur avec
// la chaîne qui correspond à l'appel de fonction et
// la chaîne qui correspond à la valeur attendue.
//
//
#define TEST_IF_EQUAL(x,y) if (x != y) { \
std::cout << "!!! Erreur !!! " << #x << " != " << #y << std::endl; \
} else { \
std::cout << #x << " = " << #y << std::endl; \
}
...
/* ------------------------------------------------------------------
QUOI
Fonction qui retourne le bit le plus significatif de son
opérande x.
COMMENT
comment allez-vous implanter la fonction
VALEUR DE RETOUR
Si x == 0, on retourne le code d'erreur 255
sinon, si x == 1, on retourne 0, puisque 2^0 = 1
etc.
------------------------------------------------------------------ */
u32 msb( u32 x ) {
...
return ...;
}
/* ------------------------------------------------------------------
QUOI
Fonction principale qui réalise les tests
------------------------------------------------------------------ */
int main() {
// Tests liés à la fonction msb(x)
TEST_IF_EQUAL( msb( 0 ), 255);
TEST_IF_EQUAL( msb( 1 ), 0);
TEST_IF_EQUAL( msb( 2 ), 1);
TEST_IF_EQUAL( msb( 255 ), 7);
TEST_IF_EQUAL( msb( 0x800F0000 ), 31);
...
return EXIT_SUCCESS;
}
Exercice 6.1
Ecrire une fonction u32 msb(u32 x) qui cherche le bit le plus significatif (most significant bit) d'un entier non signé. Le bit le plus significatif est le bit d'indice le plus haut qui est à 1.
La fonction doit retourner les valeurs suivantes :
- pour $x=0$, on retourne $255$, il s'agit d'un code d'erreur, puisque la valeur $0$ correspond à la valeur que doit retourner la fonction pour $x=1$
- pour $x=1$ ($2^0$), on retourne $0$
- pour $x=2$ ($2^1$), on retourne $1$
- pour $x=255$ ($1111\_1111_2$), on retourne $7$
- pour $x=800F0000_{16}$, on retourne $31$
Pour aller plus loin
Il existe d'autres moyens d'obtenir cette valeur en utilisant
- le type double du langage C/C++.
- ou la fonction __builtin_clz du compilateur gcc/g++
- ou l'instruction assembleur bsr
Exercice 6.2
Ecrire une fonction u32 popcnt(u32 x) qui calcule le nombre de bits à 1 dans $x$. popcnt est l'abréviation de population count.
La fonction doit retourner les valeurs suivantes :
- pour $x=0$, on retourne $0$
- pour $x=1$, on retourne $1$
- pour $x=15$, on retourne $4$
- pour $x=204=1100\_1100_2$, on retourne $4$
- pour $x=FF\_FF\_FF\_FF_{16}$, on retourne $32$
Exercice 6.3
Ecrire une fonction bool even(u32 x) qui indique si un nombre est pair.
Exercice 6.4
Ecrire une fonction bool is_power_of_2(u32 x) qui indique si le nombre x est une puissance de 2.
- pour $x=0$, on retourne false
- pour $x=1$, on retourne true
- pour $x=2$, on retourne true
- pour $x=3$, on retourne false
- pour $x=255$, on retourne false