This repository has been archived on 2019-08-08. You can view files and clone it, but cannot push or open issues or pull requests.
s1-tp/S1/TP 9/nombre.py
2014-11-28 00:22:50 +01:00

359 lines
9.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 quun nombre entier est pair ou impair lorsquon 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 quon 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 lalgorithme 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 dabord 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 dapplication 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 lalgorithme vu en cours, réalisez une fonction que vous nommerez
# bin_inv qui fait le travail inverse de la fonction bin, cest-à-dire qui
# calcule lentier 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 à lalgorithme de lécriture binaire dun nombre pour
# calculer la représentation hexadécimale dun 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, cestàdire la
# fonction qui, à partir dune chaîne de donnant lécriture hexadécimale dun
# 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)