# PREUD'HOMME BONTOUX Geoffrey - PeiP 12 - 2014/2015 # TP n°9 donné le 21/11/2014 - Exercices sur la représentation des nombres # http://www.fil.univ-lille1.fr/~wegrzyno/portail/Info/Doc/HTML/seq6_binaire.html#exercices import doctest # Exercice Écritures # Écrire en binaire le nombre n=2014. # En calculant : # 2014 = 2 × 1007 + 0 # 1007 = 2 × 503 + 1 # 503 = 2 × 251 + 1 # 251 = 2 × 125 + 1 # 125 = 2 × 62 + 1 # 62 = 2 × 31 + 0 # 31 = 2 × 15 + 1 # 15 = 2 × 7 + 1 # 7 = 2 × 3 + 1 # 3 = 2 × 1 + 1 # 1 = 2 × 0 + 1 # 0b11111011110 # Avec Python # >>> bin(n) # '0b11111011110' # Déterminez les écritures octale et hexadécimale de ce nombre de deux façons # différentes. # En calculant # 2014 = 8 × 251 + 6 # 251 = 8 × 31 + 3 # 31 = 8 × 3 + 7 # 3 = 8 × 0 + 3 # 0o3736 # Avec Python # >>> oct(2014) # '0o3736' # En calculant # 2014 = 16 × 125 + 14 # E # 125 = 16 × 7 + 13 # D # 7 = 16 × 0 + 7 # 0x7de # Avec Python # >>> hex(2014) # '0x7de' # Exercice Pair ou impair ? # Comment reconnaître qu’un nombre entier est pair ou impair lorsqu’on dispose # de son écriture binaire ? # Le dernier chiffre binaire détermine si un nombre est pair ou non (les # puissance de deux supérieures à 0 étant forcément paires, leur somme ne peut # donner qu'un nombre pair) # Le prélicat suivant permet de déterminer si un nombre est pair def bin_est_pair(b): """ Indique si le nombre binaire est pair bin → bool >>> bin_est_pair('0b11111011110') True >>> bin_est_pair('0b10101011') False """ return b[-1] == '0' # Exercice # Quel est le plus grand nombre entier qu’on peut écrire en binaire avec # 8 bits ? # Comparez ces nombres avec 2^t pour t=8,32,64. # 0b11111111 = 1 × 2^0 + 1 × 2^1 + 1 × 2^2 + 1 × 2^3 + 1 × 2^4 + 1 × 2^5 + 1 × # 2^6 + 1 × 2^7 = 2^8-1 = 255 # 32 bits ? # 0b11111111111111111111111111111111 # = 1 × 2^0 + 1 × 2^1 + 1 × 2^2 + 1 × 2^3 + 1 × 2^4 + 1 × 2^5 + 1 × 2^6 + 1 × # 2^7 + 1 × 2^8 + 1 × 2^9 + 1 × 2^10 + 1 × 2^11 + 1 × 2^12 + 1 × 2^13 + 1 × 2^14 # + 1 × 2^15 + 1 × 2^16 + 1 × 2^17 + 1 × 2^18 + 1 × 2^19 + 1 × 2^20 + 1 × 2^21 + # 1 × 2^22 + 1 × 2^23 + 1 × 2^24 + 1 × 2^25 + 1 × 2^26 + 1 × 2^27 + 1 × 2^28 + 1 # × 2^29 + 1 × 2^30 + 1 × 2^31 # = 2^16-1 = 4 294 967 295 # 64 bits ? # 0b1111111111111111111111111111111111111111111111111111111111111111 # = 1 × 2^0 + 1 × 2^1 + 1 × 2^2 + 1 × 2^3 + 1 × 2^4 + 1 × 2^5 + 1 × 2^6 + 1 × # 2^7 + 1 × 2^8 + 1 × 2^9 + 1 × 2^10 + 1 × 2^11 + 1 × 2^12 + 1 × 2^13 + 1 × 2^14 # + 1 × 2^15 + 1 × 2^16 + 1 × 2^17 + 1 × 2^18 + 1 × 2^19 + 1 × 2^20 + 1 × 2^21 + # 1 × 2^22 + 1 × 2^23 + 1 × 2^24 + 1 × 2^25 + 1 × 2^26 + 1 × 2^27 + 1 × 2^28 + 1 # × 2^29 + 1 × 2^30 + 1 × 2^31 + 1 × 2^32 + 1 × 2^33 + 1 × 2^34 + 1 × 2^35 + 1 × # 2^36 + 1 × 2^37 + 1 × 2^38 + 1 × 2^39 + 1 × 2^40 + 1 × 2^41 + 1 × 2^42 + 1 × # 2^43 + 1 × 2^44 + 1 × 2^45 + 1 × 2^46 + 1 × 2^47 + 1 × 2^48 + 1 × 2^49 + 1 × # 2^50 + 1 × 2^51 + 1 × 2^52 + 1 × 2^53 + 1 × 2^54 + 1 × 2^55 + 1 × 2^56 + 1 × # 2^57 + 1 × 2^58 + 1 × 2^59 + 1 × 2^60 + 1 × 2^61 + 1 × 2^62 + 1 × 2^63 # = 2^64-1 = 18 446 744 073 709 551 615 # Exercice fonction ``mon_bin`` # En suivant l’algorithme de conversion vu dans le cours, programmez une # fonction que vous nommerez mon_bin qui agit exactement de la même façon que la # fonction bin de Python. Concevez d’abord votre fonction pour des nombres # positifs def mon_bin(d): """ Équivalent de la fonction native bin() définie sur les entiers positifs int → bin CU : int strictement positif >>> mon_bin(2014) '0b11111011110' >>> mon_bin(42) '0b101010' """ assert(d > 0), "d doit être strictement positif" D = d r = '' while D >= 1: r = str(D % 2) + r D = D // 2 return '0b' + r # Observez les réponses fournies par votre fonction pour plusieurs nombres # positifs, puis pour 0. Est-ce que tout est correct ? # >>> mon_bin(2014) # '0b11111011110' # >>> mon_bin(42) # '0b101010' # >>> mon_bin(0) # '0b' # >>> mon_bin(-42) # '0b' # Chaque nombre ≤ 0 donné renverra '0b'. Cela est dû au fait qu'on vérifie que # D ≥ 1. On devrait utiliser sa valeur absolue, soit vérifier que |D| ≥ 1. # Cependant, on remarque que l'instruction D // 2 arrondit à l'entier inférieur, # la fonction restera bloqué avec un D valant -1. On préfèrera prendre la valeur # absolue de d au départ et rajouter un - au résultat, plutôt que de vérifier # si l'arrondi doit être fait à l'entier supérieur ou inférieur à l'intérieur # de la boucle, ce qui prendrait trop de temps. # Étendez le domaine d’application de votre fonction au cas de 0 et des nombres # négatifs. def mon_bin2(d): """ Équivalent de la fonction native bin() int → bin >>> mon_bin2(2014) '0b11111011110' >>> mon_bin2(42) '0b101010' >>> mon_bin2(0) '0b0' >>> mon_bin2(-42) '-0b101010' """ D = abs(d) if d != 0: r = '' while D >= 1: r = str(D % 2) + r D = D // 2 else: r = '0' return ('-' if d < 0 else '') + '0b' + r # Exercice fonction ``bin_inv`` # En utilsant l’algorithme vu en cours, réalisez une fonction que vous nommerez # bin_inv qui fait le travail inverse de la fonction bin, c’est-à-dire qui # calcule l’entier correspondant à une chaîne de caractères décrivant cet entier # en binaire. def bin_inv(b): """ Réalise le travail inverse de la fonction native bin() bin → int >>> bin_inv ('0b101111') 47 >>> bin_inv ('-0b101111') -47 """ B = b.replace('0b', '') if b[0] == '-': B = B.replace('-', '') d = 0 if len(B) > 0: for i in range(-1, -len(B) - 1, -1): d += int(B[i]) * 2 ** (-i - 1) return -d if b[0] == '-' else d # Exercice fonction ``mon_hex`` # Que faut-il changer à l’algorithme de l’écriture binaire d’un nombre pour # calculer la représentation hexadécimale d’un nombre entier naturel non nul ? # Il faut remplacer les divisions par deux par des divisions par 16, et # remplacer les nombres au dessus de 10 par des lettres. On utilisera une # autre fonction pour cela, elle pourra très probablement resservir # Réalisez une fonction que vous nommerez mon_hex équivalente à la fonction hex. # Commencez pour les nombres positifs, puis envisagez le cas des nombres # négatifs. def mon_hex_unique(d): """ Équivalent de la fonction native hex() pour un seul caractère héxadécimal int → hex CU : 0 ≤ d < 16 >>> mon_hex_unique(11) 'b' >>> mon_hex_unique(8) '8' """ assert(type(d) is int and d >= 0 and d < 16), "" return chr(97 + d - 10) if d >= 10 else str(d) def mon_hex(d): """ Équivalent de la fonction native hex() int → hex >>> mon_hex(47) '0x2f' >>> mon_hex(-47) '-0x2f' """ D = abs(d) if d != 0: r = '' while D >= 1: r = mon_hex_unique(D % 16) + r D = D // 16 else: r = '0' return ('-' if d < 0 else '') + '0x' + r # Exercice fonction ``hex_inv`` # Réalisez la fonction hex_inv inverse de la fonction hex, c’est–à–dire la # fonction qui, à partir d’une chaîne de donnant l’écriture hexadécimale d’un # entier, calcule cet entier. Vous devez obtenir par exemple: def hex_inv_unique(h): """ Réalise le travail inverse de la fonction native hex() pour un seul caractère héxadécimal hex → int >>> hex_inv_unique('b') 11 >>> hex_inv_unique('8') 8 """ return ord(h) - 97 + 10 if ord(h) >= 97 else int(h) def hex_inv(h): """ Réalise le travail inverse de la fonction native hex() hex → int >>> hex_inv ('0x2f') 47 >>> hex_inv ('-0x2f') -47 """ H = h.replace('0x', '') if h[0] == '-': H = H.replace('-', '') d = 0 if len(H) > 0: for i in range(-1, -len(H) - 1, -1): d += hex_inv_unique(H[i]) * 16 ** (-i - 1) return -d if h[0] == '-' else d # Exercice fonction ``bin_en_hex`` # Sans utiliser les fonctions hex et/ou bin (ni même mon_bin et/ou mon_hex), # programmez une fonction nommée bin_en_hex qui convertit une chaîne de # caractères représentant un nombre entier écrit en binaire en la chaîne # hexadécimale représentant le même entier. # Notez bien dans cet exemple que la valeur passée en argument à la fonction # bin_en_hex est une chaîne de caractères. def bin_en_hex(b): """ Convertit un binaire en hexadécimal bin → hex >>> bin_en_hex('0b101111') '0x2f' >>> bin_en_hex('-0b101111') '-0x2f' """ B = b.replace('0b', '') if b[0] == '-': B = B.replace('-', '') if len(B) > 0: r = '' for i in range(-1, -len(B) - 1, -4): p = 0 # On coupe le binaire en partie de 4 chiffres for j in range(4): rang = i - j if -rang <= len(B): p += int(B[rang]) * 2 ** (j) else: p += 0 r = mon_hex_unique(p) + r else: r = '0' return ('-' if b[0] == '-' else '') + '0x' + r def tester(): doctest.testmod(verbose=True)