Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 30-12-2022 14:49:25

Vani94
Membre
Inscription : 04-11-2022
Messages : 26

Système binaire sur python

Bonjour,
Je bloque sur 2 programme python, pourriez-vous m'aider, s'il vous plaît ?

Voici l'énoncé :

https://drive.google.com/file/d/1Lbvdx- … p=drivesdk


Pour le premier je ne comprends pas trop à quoi correspondent i et p et pourquoi on les soustrait ensemble.

Pour le 2 ème j'ai essayé en prenant comme modèle le premier :

From math import *
def binaire (n) :
       L = [  ]
       n =
       while n > 0 :
              n = n //2
              r  = n%2
              L = [ r ]
L.reverse ()
return (L)

Dernière modification par Vani94 (30-12-2022 14:51:42)

Hors ligne

#2 31-12-2022 17:37:31

Black Jack
Membre
Inscription : 15-12-2017
Messages : 509

Re : Système binaire sur python

Bonjour,

Si tu écris une fonction avec un paramètre à lui passer (ici n) ...
Il ne faut pas entrer la valeur de n dans la dite fonction.

Il faut passer ce paramètre n par l'appel de la fonction dans le programme principal.

Il y a, me semble-t-il, quelques lignes à la syntaxe bizarre et quelques autres bizarreries dans ton programme, en le modifiant juste un peu, j'arrive à ceci :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
            rev_L = L[::-1]
       return (rev_L)

n=input("entrez n :")
n=int(n)
print(binaire(n))

Essaie de comprendre et modifie au besoin pour utiliser des instructions qui te sont connues.

La ligne "rev_L = L[::-1]" permet d'inverser la liste L, il existe plein d'autres manières de réaliser cela.

Hors ligne

#3 31-12-2022 22:17:56

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : Système binaire sur python

B'soir,

Black Jack a écrit :

La ligne "rev_L = L[::-1]" permet d'inverser la liste L, il existe plein d'autres manières de réaliser cela.

La méthode à utiliser lui est suggérée dans le document en lien dans son post : la "méthode" (c'est comme ça que ça s'appelle) reverse.
Cette méthode présente la particularité d'inverser en place : il faut comprendre l'expression "en place" comme "ne nécessitant pas de liste supplémentaire".
Syntaxe : L.reverse()
Cela dit, je trouve la syntaxe rev_L=L[::-1]
- bien plus pythonesque, plus amusante (C'est celle que je préfère)
- plus exigeante en ce sens qu'elle demande de bien maîtriser l'emploi des listes

Le procédé décrit dans le document n'est rien d'autre que la méthode classique qu'on utilise "à la main"


 47  | 2
 07  | 23  | 2   
  1  | 03  | 11  | 2
        1  |  1  | 5  | 2
                   1  | 2  | 2
                        0  | 1

On lit le résultat de bas en haut, en diagonale et commençant par le dernier quotient et suivi par les restes en remontant : 101111...
Encore faut-il savoir faire les divisions à "l'ancienne" sans poser les soustractions parce qu'alors, cette façon de faire devient "imbuvable"...

Dans le document en lien, en bas à droite dans l'encadré, où on présente Reverse(), on signale aussi le moyen de trouver le quotient euclidien de a par b sans écrire int(a/b) : on écrit a//b...
C'est cela qu'il faut utiliser vani94...

Donc, je profite de l'occasion pour signaler qu'en Python, une instruction permet d'obtenir en une seule fois le quotient et le reste : divmod...
Syntaxe : q,r=divmod(a,b)
Ainsi, par exemple :

q,r=divmod(97,7)
print(q,r)

renvoie : 13 6
$97 =7 \times 13 +6$...

Je reviendrai demain sur la première question :
je n'avais pas pigé, jusqu'à ce soir, que les fonctions du document allaient ensemble...
Compléter la 1ere fonction allait de soi et j'ai passé 24 h à pondre une suite qui veuille bien fonctionner : évidemment, j'ai fait quelque chose de compliqué, très compliqué !
J'en admire donc la simplicité de la 2e fonction...

J'expliquerai demain...
le m-p qui t'intrigue tant sert à placer des 1 au bon endroit dans la liste pour ne pas avoir à la retourner à la fin...
La première fonction : plus_grande_puiss_2(n) recherche la plus grande puissance de 2 contenue dans un nombre n.
Ici l'exemple traité est 58.
Avec 58, cette plus grande puissance est 5...
On utilise une boucle while (Tant Que) :
while p<=n:
Il faut d'abord, avant d'utiliser p dans la condition d'arrêt, que
1. p soit connu --> sinon message d'erreur
2. p soit inférieur ou égal à n --> sinon la boucle ne démarre pas
Donc, avant d'entrer dans la boucle, 1. on fixe la valeur de p à 1 : p=1...
Mais, dans la boucle, l'exposant que l'on cherche s'appelle i, et on va l'augmenter à chaque tour.
Pour l'augmenter :
1. Il doit être connu
2. Il doit avoir une valeur de départ
D'où le i =0 avant d'entrer dans la boucle...

Et dans la boucle on va calculer $2^0,\;2^1,\;2^2,\;2^3...$ ça ce sont les valeurs successives de p (l'exposant c'est i) que la boucle, une fois calcul fait, va chercher si p<=n.
Tant que c'est vrai on calcule les puissances de 2.
Pour sortir de la boucle, il faut avoir un p>n...
Mais alors le i est trop grand de 1, on retourne donc non pas i, mais i-1 : return (i-1)...
J'ai écrit que pour 58, la plus grande puissance est 5 :
En effet : $2^5=32$....
Et la boucle est allée jusqu'à $2^6=64$ parce que 32 est <= 58, donc un tour supplémentaire a été fait jusqu'à p=64, alors p> n et on sort de la boucle avec i=6... et on renvoie 6-1, soit le nombre 5...
Voilà, tu peux compléter cette première fonction.

Ainsi que dit, je reviendrai demain sur la 2e...

@+

Bonne année 2023 à tous !

Hors ligne

#4 01-01-2023 14:04:08

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : Système binaire sur python

Bonjour,

Un point sur le binaire.
Un nombre est composé d'octets : 1 octet représente 8 chiffres (pris parmi 0 et 1)
Plus petit nombre composé d'un octet : 0.
Un octet est représenté dans 1 tableau de 8 cases, chaque case se nomme bit (Attention à ne pas confondre, le mot anglais pour octet est byte.                                       
Voilà l'octet correspondant :
_______________
|0|0|0|0|0|0|0|0|
Plus grand nombre composé d'un octet : 255
Voilà l'octet correspondant :
_______________
|1|1|1|1|1|1|1|1|
chaque case a une valeur de 1 ou 0, multipliés par (de gauche à droite)
$2^7,\,2^6,\,2^5,\,2^4,\,2^3,\,2^2,\,2^1,\,2^0$
soit
$128,\,64,\,32,\,16,\,8,\,4,\,2,\,1$
Donc,
$128\times 1+64\times 1+32\times 1+16\times 1+\times 1+4\times 1+2\times 1+1\times 1= 128+64+32+16+8+4+2+1=255$

Autre exemple :
|1|0|0|1|0|0|1|1| c'est à dire 128+0+0+16+0+0+2+1 = 147
Contrôle avec Python...
Python convertit en binaire mais affiche une chaîne de caractères, pas un nombre :

print(bin(147))
 

Réponse :
0b10010011 le 0b indique que ce qui suit est du binaire.
Si je veux ne pas afficher le 0b, je tape :

print(bin(147)[2:])
 

qui affiche
10010011
Si je cherche la plus grande puissance de 2 contenue dans 147, je trouve 7 (2**7 =128).
Le 1er chiffre du nombre binaire est 1 dans la 8e case, le 8e bit (on compte de droite à gauche).
Le 8e bit est la puissance 7 de 2
32 est 2**5. La puissance 5 est dans le 6e bit
8 est 2**3. La puissance 3 est dans le 4e bit.
Ne pas oublier que droite à gauche les bits valent 0, 1 ,2 , 3, 4, 5, 6, 7  de 0 à 7, il y a bien 8 chiffres...

Alors, voyons de façon détaillée comment fonctionne la fonction : binaire(n).
Soit n = 58.
m= plus_grande_puiss_2(58)=5 ($2^5=32$ mais $2^6=64$ donc c'est 5).
Donc m = 5... et c'est la puissance maximum.
Ici, les puissances peuvent varier de 5 à 0 : soit 6 puissances possibles et donc 6 éléments dans la liste (5+1)
Là, on crée la liste L qui commence par 1 :
Quel que soit le nombre (autre que 0, bien sûr), dans n'importe quelle base, il commence par un chiffre de 1 à 9, jamais par un 0...
Donc on ajoute à la liste [1], une liste contenant m zéros (ici 5 zéros : [0]*5 --> [0,0,0,0,0]).
Et on calcule le nouveau n : n =58 - 2^5 = 58 -32 =26 (En Python, n-2**m)
On entre dans la boucle : while n!=0:
(Tant que n est différent de zéro : c'est la condition, le test de sortie de la boucle. Cette sortie ne se produira que si - après calcul - le nouveau n vaut 0)
Avant d'entrer dans la boucle, la liste L est donc [1,0,0,0,0,0] (elle comprend 6 éléments) et n=26...
26 est différent de 0, on entre dans la boucle...
Et on va s'occuper dans l'ordre, des 2e, 3e, 4e, 5e, 6e élément, donc de L[1], L[2], L[3], L[4], L[5] : ne pas perdre de vue qu'en Python les indices commencent à 0 : le 1er élément a donc l'indice 0...
En fait, les éléments valent 1 ou 0...
Donc, on n'a besoin que d'écrire 1, si c'est 0, on l'a déjà, pas besoin de s'en occuper...

Poursuivons...
A peine entré dans la boucle, on cherche p la plus grande_puissance de 2 contenue dans n=26, c'est p=4.
(Encore une fois 2**4 = 16  et 2**5 = 32 et on a bien 16 <26 <32.
Donc il faut mettre 1 pour la puissance 4, dans la liste...
Cette puissance 4 est juste avant la puissance 5.
La puissance 5 est dans la première case, dans L[0]...
Donc le 1 pour 2**4 va être dans L[1]...
Comment trouver l'indice 1 ?

L'indice est 0 pour la puissance 5.
Donc 5, puissance maxi --> il y a 1 à l'indice 0 (L[0]=1)
Et on en vient à m-p
puissance 5 (maxi) et indice 0 : L[0] =1
puissance 4 : elle suit immédiatement (comme dans un octet) la puissance 5 donc --> L[1]=1...
et 1 = 5 - 4...
Il faut vérifier si ça marche toujours...
On a maintenant L= [1,1,0,0,0,0]

Et on calcule 26-2**4= 26 - 16 = 10
plus grande puissance de 2 contenue dans 10 ? Réponse : p=3... 2**3=8
la puissance 3 précède la puissance 4, le 1 pour pour la puissance 4 est en L[1] donc le 1 pour la puissance 3 sera en L[2] et m-p = 5-3=2
Ça marche...
L=[1,1,1,0,0,0]
Et on calcule  n = 10 - 2**3 =10 - 8 =2.

Plus grande puissance de 2 contenue dans 2 : Réponse p =1
Normalement, on met 1 dans L[5 -1) soit L[4]...
La puissance 1 est avant la puissance 2 qui était avant la puissance 3, donc on doit sauter une case et passer de L[2] à L[4]...
Donc L[4]=1, la case L[3] restant donc à 0...
Enfin n=2-2**1 =0 : la condition n!=0 (rappel en maths c'est $n\neq 0$) n'étant plus remplie on sort de la boucle sans toucher à L[5] qui reste à 0.
On a donc L= qu'on écrit $\overline {11010}^2$...
Le L[m-p] est une grande subtilité : si on n'a pas l'habitude jouer avec les indices des listes, et c'est le cas des débutants, non seulement on ne le trouve pas, mais on a ta réaction : << Je comprends pas pourquoi ce m-p >> !

En résumé m étant fixé (m=5), l'exposant p décroissant de 5 à 1, m-p croît de 0 à 4...
m-p étant l'indice des 1 dans L, on avance donc L[0] à L[4].
Les 1 et les 0 étant rangés dans le bon ordre (celui des bits des octets), il n'y a pas besoin de renverser l'ordre de la liste à la fin.

Question subsidiaire:
Python est-il capable de passer de L=[1,1,1,0,1,0] au nombre $\overline{111010}^2$ ?
Oui, 3 méthodes
1. Basique (mais je joue avec les indices)

L=[1,1,1,0,1,0]
nb=0
for i in range(0,6):
    nb=nb+L[i]*10**(5-i)
print(nb)
 

qui me donne
111010

2. Un peu plus évoluée (et un peu plus rapide et pythonesque)

nb,L=0,[1,1,1,0,1,0]
for i,c in enumerate (L):
    nb+=c*10**(5-i)
print(nb)
 

., mais c'est plus long...

ch,L="",[1,1,1,0,1,0]
L=[str(i) for i in L] # Conversion de chaque élément de L en une chaîne (string).
ch="".join(L) # méthode qui ne fonctionne qu'avec des chaînes...
print(ch)
 

Question(s) ?

@Black Jack
Ton code me chiffonne :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
            rev_L = L[::-1]
       return (rev_L)

Pourtant, ton code fonctionne aussi, je n'ai pas réussi à le prendre en défaut...
Parce que j'écrirais plutôt :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
       rev_L = L[::-1]
       return (rev_L)

@+

Dernière modification par yoshi (01-01-2023 20:10:24)

Hors ligne

#5 01-01-2023 15:17:39

Vani94
Membre
Inscription : 04-11-2022
Messages : 26

Re : Système binaire sur python

Bonjour à tous et merci pour votre aide, je comprends mieux comment fonctionne le programme toutefois j'ai quelques questions :

Pour le premier programme, si j'ai bien compris p prend successivement les valeurs de 2^i dans la boucle qui vérifie que p<= n mais dans ce cas si j'ai fixer la valeur de p à 1 au départ je ne peux pas mettre directement p = 2**i dans la boucle non ?? À moins que je le remplace par p = (1+1)**i....
Pour le raisonnement sur les listes, ça veut dire que quand on trouve une puissance de 2 pour un nombre n, 1 s'affiche dans la liste mais quand vous parlez de $2^5$, $2^4$ et $2^3$, la seul raison donc pour laquelle le 1 de $2^4$ est avant le 0 de $2^5$ dans la liste c'est parce qu'on ne peut pas commencer une liste par un 0 ?

Pour le 2e programme, c'est important de rajouter le int dans n = int(n/2) ou c'est juste pour remplacer n//2 ? Et que signifie rev_L = L[::-1] ??

Hors ligne

#6 01-01-2023 18:19:26

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : Système binaire sur python

Bonjour,

En ce qui concerne la fonction plus grande puissance,  la condition pour entrer (et rester) dans la boucle est sur la ligne while p<=n: et demande que p<=n :
Revoyons le fonctionnement :
while p<=n:  (=Tant que p est inférieur ou égal à n)
Mettons que n=21, si tu fixes, avant la boucle p=22, que se passe-t-il ?
Le programme vérifie si p<=n, donc si 22 <=21, constate que non et donc ne rentre pas das la boucle, saute directement à return i-1 et comme on a fixé i =0 avant la boucle, la fonction retourne i-1, c'est à dire -1...
Peu importe la valeur donnée, avant la boucle, à p, pourvu que p<=n alors on peut rentrer dans la boucle...

Oui, mais après, il n'y aurait pas de pb dans la boucle ?
Reprends n=21.
Que fait la fonction ?
Dans la boucle, elle prend i=0+1, calcule $p=2^1=2$ et retourne au poste de contrôle :
toc ! toc !
J'ai p =2, je peux continuer les calculs ?
Hmmmm... Voyons cela : 2 <=21 ? Oui !
Vous pouvez continuer...

On augmente i de 1 :  i = i+1 = 2 et on calcule p : $p =2^2 = 4$..
Retour au Poste de Contrôle :
toc ! toc !
J'ai p =4, je peux continuer les calculs ?
Hmmmm... Voyons cela : 4 <=21 ? Oui !
Vous pouvez continuer...

On augmente i de 1 :  i = 2+1 = 32 et on calcule p : $p =2^3 = 8$.
Retour au Poste de Contrôle :
toc ! toc !
J'ai p =8, je peux continuer les calculs ?
Hmmmm... Voyons cela : 8 <=21 ? Oui !
Vous pouvez continuer...

On augmente i de 1 :  i = 3+1 = 4 et on calcule p : $p =2^4 = 16$.
Retour au Poste de Contrôle :
toc ! toc !
J'ai p =16, je peux continuer les calculs ?
Hmmmm... Voyons cela : 16 <=21 ? Oui !
Vous pouvez continuer...

On augmente i de 1 :  i = 4+1 = 5 et on calcule p : $p =2^5 = 32$.
Retour au Poste de Contrôle :
toc ! toc !
J'ai p =32, je peux continuer les calculs ?
Hmmmm... Voyons cela : 32 <=21 ? Non !
Vous ne pouvez pas continuer les calculs, vous sortez !

Alors tu sors et tu retournes dans la 2e fonction (qui t'a envoyée dans Plus grande puissance)  avec i-1 = 5-1= 4 comme puissance cherchée...
Et si avant la boucle tu avais fixé p=0 ou par exemple p=13 ça aurait changé quoi dans les calculs de la boucle ?

Vani94 a écrit :

si j'ai fixer la valeur de p à 1 au départ je ne peux pas mettre directement p = 2**i dans la boucle non ?? À moins que je le remplace par p = (1+1)**i

Euh... Ca change quoi d'écrire (1+1)**i au lieu de 2**i  ????
Priorité des opérations  :
l'opération dans les parenthèses est prioritaire sur la puissance...
Suppose i=3.
S'il n'y avait pas de parenthèses 1+1**3 = 1+1 =2 mais (1+1)**3 =2**3 = 8...
Mais la parenthèse se calcule d'abord :
- on calcule 1+1 et on trouve 2, puis on applique la puissance : 2**3 =8...
On aura toujours ...(1+1)**i =2**i

Un nombre quel qu'il soit ne commence pas par un 0 sauf dans les anciens compteurs kilométriques de voiture où il y avait plusieurs roulettes (6) je crois, avec les chiffres 0,1,2,3,4,5,6,7,8,9 répartis tout le tour des roulettes.
Ces compteurs pouvaient afficher de 0 à 999 999 km
Et le compteur pouvait afficher 058452 km parce que avec 58452 km, la roulette tout à gauche des centaines de milliers n'était pas encore passée de 0 à 1...
Sinon, ça sert à quoi, dans la vie, en maths d'écrire : cet objet m'a coûté  025 € ?.
Mais si, une liste peut commencer par un 0, on peut dans une liste (en Python ou un autre langage) écrire des nombres entiers naturels, des entiers relatifs, des décimaux, des nombres fractionnaires, des réels, des lettres à condition de les encadrer par des guillemets anglais : "F"   ou par des ' comme ceci : 'F'...
Sinon le langage de programmation "pense" que cette lettre est une variable  :
si la valeur de la lettre est connue, lorsque tu affiches la liste, la lettre est remplacée par sa valeur, sinon message d'erreur (en anglais) qui dit en gros : je ne connais pas cette lettre !.
On peut même stocker des mots, des expressions complètes :
L=[0, -2, 3.5, -8/3, "chien", "je ne suis pas d'accord !"]

Les indices d'une liste partent de 0 à .... (en Python plusieurs milliard) :
Avec la liste L ci-dessus :
L[0] vaut 0
L[1] vaut -2
L[2] vaut 3.5
L[3] vaut -8/3
L[4] vaut "chien"
L[5] vaut "je ne suis pas d'accord !"

Mais; prenons un nombre écrit en base 2, par exemple 1101011101.
De G à D dans le sens de la lecture (ou de l'écriture), ce nombre se transforme en base dix par ce calcul :
$2^9\times 1+2^8\times 1+2^7\times 0+2^6\times 1+2^5\times 0+2^4\times 1+2^3\times 1+2^2\times 1+2^1 \times 0+2^0\times 1$
La plus grande puissance est tout à G, la plus petite tout à D...

Quand j'ai écrit :
Cette puissance 4 est juste avant la puissance 5.
je n'ai pas été assez clair ! Toutes mes excuses...
Un nombre s'écrit en commençant par la valeur la plus élevée de l'exposant.
Si j'écris en base dix : 345687, c'est
$3\times 10^5+4\times 10^4+5\times 10^3+6\times 10^2+8\times 10^1+7\times 10^0$

Dans l'ordre de la lecture le $10^4$ est après $10^5$
Dans la liste censée contenir, l'un après l'autre les chiffres, du nombre, la puissance la plus élevée occupe la case d'indice plus faible.
Ainsi, si je décompose dans une liste, chiffre par chiffre, le nombre 110101


Liste               : [1  ,  1  ,   0  ,  1 ,  0  ,  1]
les indices sont    :  0     1      2     3    4     5    
les puissances sont :  5     4      3     2    1     0
 

------------------------------------------------
Cette puissance 4 est juste avant la puissance 5 : dans le sens de lecture des puissances de 2 décroissantes du nombre 58
Ou encore, comme je l'avais écrit :

puissance 5 (maxi) et indice 0 : L[0] =1
puissance 4 : elle suit immédiatement (comme dans un octet) la puissance 5 donc --> L[1]=1

La puissance 3, si elle existe, dans la liste, correspondra à L[2], L[2]=1
Si elle n'existe pas, on laisse 0 dans L[2] et on continue les calculs...

Mais je n'ai pas trouvé où je disais qu'il y avait 0 pour $2^5$ et 1 pour $2^4$ ...
Tu voulais parler de l'indice 0 qui désigne l'emplacement L[0] ?

Je reprends les calculs avec n=58 et le pourquoi de L[m-p]=1...

Plus grand exposant pour n=58 ? C'est 5 et c'est l'exposant maximum puisque 58 est le nombre de départ. On note m=5...
En effet $2^5=32 \leqslant 58 < 2^6=64$
Puisque 5 est l'exposant maxi, cela permet d'écrire une liste avec 1 et 5 zéros à la suite : [1,0,0,0,0,0].
Je pourrais dire que p (encore pas calculé dans la boucle) vaut 5 aussi puisque c'est le plus grand exposant de 2 pour le nombre 58.
m-p =0 et dans L[m-p] c'est à dire dans L[0], on trouve bien 1...
$n =58-32 = 26$

On rentre dans la boucle.
Plus grand exposant de 2 pour 26 ? C'est p=4. En effet  $2^4=16 \leqslant 26<2^5=32$
Donc l'exposant 4 existe et on avait trouvé juste avant l'exposant 5 pour lequel figurait 1 dans L[0]...
5 et 4 se suivent, peu importe l'ordre... On va devoir écrire 1 à la suite dans la liste, c'est à dire dans L[1]...
Et là, j'avais noté que que comme m =5 et p=4, alors L[m-p]=L[1] et on retrouve ce que j'ai déduis à la ligne précédente...
$n= 26-2^4=26-16 =10$

Plus grand exposant de 2 pour 10 ? C'est p=3. En effet $2^3=8\leqslant 10 <2^4=16$
Comme p=4 d'avant et le p=3 maintenant sont consécutifs,  le 1 à mettre dans la liste ira "à la suite" du 1 qu'on vient d'inscrire, donc L[2]=1. Et m=5, p=3 --> m-p=2.
A ce stade la liste est devenue [1,1,1,0,0,0]
$n=10-2^3= 10-8 =2$

Plus grand exposant pour 2 ? C'est p=1. En effet $2^1 \leqslant 2<2^2=4$
Mais le p=3 d'avant et le p=1 maintenant ne sont pas consécutifs (2 d'écart) : il faut sauter la case L[3] et écrire 1 dans la case L[4]
A ce stade la liste est devenue [1,1,1,0,1,0]
$n=2-2^1=0$

La condition $n\neq 0$ (en Python : n !=0) n'est plus vérifiée, on sort de la boucle et L reste inchangé : [1,1,1,0,1,0]
A toi de jouer : fais l'essai comme demandé avec 87 et reviens présenter ton résultat.

------------------------------------------------------------------------------------------------------------

Pour le 2e programme, c'est important de rajouter le int dans n = int(n/2) ou c'est juste pour remplacer n//2 ?

n/2 =2.5 et int(n/2) =2. Par contre 5//2 = 2...

Et que signifie rev_L = L[::-1] ??]

Syntaxe :
L[indice de début: indice de fin+1: sens de parcours]
si l'indice de début n'est pas donné, il vaut 0 par défaut.
Si l'indice de fin n'est pas donné, c'est celui du dernier élément de la liste
Le sens est facultatif, s'il n'est pas présent c'est G---> D
Exemples
L=['9', '3', '7', '10', '8', '2', '6', '15', '1']
L[:3] --> ['9', '3', '7']
L[5:] --> ['2', '6', '15', '1']
L[4:7] --> ['2', '6', '15', '1']
L[7:4:-1] --> ['15', '6', '2']
L[::-1] --> ['1', '15', '6', '2', '8', '10', '7', '3', '9'] c'est l'équivalent de reverse()
['9', '3', '7', '10', '8', '2', '6', '15', '1'].reverse() --> ['1', '15', '6', '2', '8', '10', '7', '3', '9']

Tout est plus clair ?

@+

Dernière modification par yoshi (01-01-2023 21:36:49)

Hors ligne

#7 02-01-2023 14:25:24

Vani94
Membre
Inscription : 04-11-2022
Messages : 26

Re : Système binaire sur python

Oui tout est beaucoup plus clairs merci.

Hors ligne

#8 03-01-2023 19:58:13

Black Jack
Membre
Inscription : 15-12-2017
Messages : 509

Re : Système binaire sur python

yoshi a écrit :

Bonjour,

Un point sur le binaire.
Un nombre est composé d'octets : 1 octet représente 8 chiffres (pris parmi 0 et 1)
Plus petit nombre composé d'un octet : 0.
Un octet est représenté dans 1 tableau de 8 cases, chaque case se nomme bit (Attention à ne pas confondre, le mot anglais pour octet est byte.                                       
Voilà l'octet correspondant :
_______________
|0|0|0|0|0|0|0|0|
Plus grand nombre composé d'un octet : 255
Voilà l'octet correspondant :
_______________
|1|1|1|1|1|1|1|1|
chaque case a une valeur de 1 ou 0, multipliés par (de gauche à droite)
$2^7,\,2^6,\,2^5,\,2^4,\,2^3,\,2^2,\,2^1,\,2^0$
soit
$128,\,64,\,32,\,16,\,8,\,4,\,2,\,1$
Donc,
$128\times 1+64\times 1+32\times 1+16\times 1+\times 1+4\times 1+2\times 1+1\times 1= 128+64+32+16+8+4+2+1=255$

Autre exemple :
|1|0|0|1|0|0|1|1| c'est à dire 128+0+0+16+0+0+2+1 = 147
Contrôle avec Python...
Python convertit en binaire mais affiche une chaîne de caractères, pas un nombre :

print(bin(147))
 

Réponse :
0b10010011 le 0b indique que ce qui suit est du binaire.
Si je veux ne pas afficher le 0b, je tape :

print(bin(147)[2:])
 

qui affiche
10010011
Si je cherche la plus grande puissance de 2 contenue dans 147, je trouve 7 (2**7 =128).
Le 1er chiffre du nombre binaire est 1 dans la 8e case, le 8e bit (on compte de droite à gauche).
Le 8e bit est la puissance 7 de 2
32 est 2**5. La puissance 5 est dans le 6e bit
8 est 2**3. La puissance 3 est dans le 4e bit.
Ne pas oublier que droite à gauche les bits valent 0, 1 ,2 , 3, 4, 5, 6, 7  de 0 à 7, il y a bien 8 chiffres...

Alors, voyons de façon détaillée comment fonctionne la fonction : binaire(n).
Soit n = 58.
m= plus_grande_puiss_2(58)=5 ($2^5=32$ mais $2^6=64$ donc c'est 5).
Donc m = 5... et c'est la puissance maximum.
Ici, les puissances peuvent varier de 5 à 0 : soit 6 puissances possibles et donc 6 éléments dans la liste (5+1)
Là, on crée la liste L qui commence par 1 :
Quel que soit le nombre (autre que 0, bien sûr), dans n'importe quelle base, il commence par un chiffre de 1 à 9, jamais par un 0...
Donc on ajoute à la liste [1], une liste contenant m zéros (ici 5 zéros : [0]*5 --> [0,0,0,0,0]).
Et on calcule le nouveau n : n =58 - 2^5 = 58 -32 =26 (En Python, n-2**m)
On entre dans la boucle : while n!=0:
(Tant que n est différent de zéro : c'est la condition, le test de sortie de la boucle. Cette sortie ne se produira que si - après calcul - le nouveau n vaut 0)
Avant d'entrer dans la boucle, la liste L est donc [1,0,0,0,0,0] (elle comprend 6 éléments) et n=26...
26 est différent de 0, on entre dans la boucle...
Et on va s'occuper dans l'ordre, des 2e, 3e, 4e, 5e, 6e élément, donc de L[1], L[2], L[3], L[4], L[5] : ne pas perdre de vue qu'en Python les indices commencent à 0 : le 1er élément a donc l'indice 0...
En fait, les éléments valent 1 ou 0...
Donc, on n'a besoin que d'écrire 1, si c'est 0, on l'a déjà, pas besoin de s'en occuper...

Poursuivons...
A peine entré dans la boucle, on cherche p la plus grande_puissance de 2 contenue dans n=26, c'est p=4.
(Encore une fois 2**4 = 16  et 2**5 = 32 et on a bien 16 <26 <32.
Donc il faut mettre 1 pour la puissance 4, dans la liste...
Cette puissance 4 est juste avant la puissance 5.
La puissance 5 est dans la première case, dans L[0]...
Donc le 1 pour 2**4 va être dans L[1]...
Comment trouver l'indice 1 ?

L'indice est 0 pour la puissance 5.
Donc 5, puissance maxi --> il y a 1 à l'indice 0 (L[0]=1)
Et on en vient à m-p
puissance 5 (maxi) et indice 0 : L[0] =1
puissance 4 : elle suit immédiatement (comme dans un octet) la puissance 5 donc --> L[1]=1...
et 1 = 5 - 4...
Il faut vérifier si ça marche toujours...
On a maintenant L= [1,1,0,0,0,0]

Et on calcule 26-2**4= 26 - 16 = 10
plus grande puissance de 2 contenue dans 10 ? Réponse : p=3... 2**3=8
la puissance 3 précède la puissance 4, le 1 pour pour la puissance 4 est en L[1] donc le 1 pour la puissance 3 sera en L[2] et m-p = 5-3=2
Ça marche...
L=[1,1,1,0,0,0]
Et on calcule  n = 10 - 2**3 =10 - 8 =2.

Plus grande puissance de 2 contenue dans 2 : Réponse p =1
Normalement, on met 1 dans L[5 -1) soit L[4]...
La puissance 1 est avant la puissance 2 qui était avant la puissance 3, donc on doit sauter une case et passer de L[2] à L[4]...
Donc L[4]=1, la case L[3] restant donc à 0...
Enfin n=2-2**1 =0 : la condition n!=0 (rappel en maths c'est $n\neq 0$) n'étant plus remplie on sort de la boucle sans toucher à L[5] qui reste à 0.
On a donc L= qu'on écrit $\overline {11010}^2$...
Le L[m-p] est une grande subtilité : si on n'a pas l'habitude jouer avec les indices des listes, et c'est le cas des débutants, non seulement on ne le trouve pas, mais on a ta réaction : << Je comprends pas pourquoi ce m-p >> !

En résumé m étant fixé (m=5), l'exposant p décroissant de 5 à 1, m-p croît de 0 à 4...
m-p étant l'indice des 1 dans L, on avance donc L[0] à L[4].
Les 1 et les 0 étant rangés dans le bon ordre (celui des bits des octets), il n'y a pas besoin de renverser l'ordre de la liste à la fin.

Question subsidiaire:
Python est-il capable de passer de L=[1,1,1,0,1,0] au nombre $\overline{111010}^2$ ?
Oui, 3 méthodes
1. Basique (mais je joue avec les indices)

L=[1,1,1,0,1,0]
nb=0
for i in range(0,6):
    nb=nb+L[i]*10**(5-i)
print(nb)
 

qui me donne
111010

2. Un peu plus évoluée (et un peu plus rapide et pythonesque)

nb,L=0,[1,1,1,0,1,0]
for i,c in enumerate (L):
    nb+=c*10**(5-i)
print(nb)
 

., mais c'est plus long...

ch,L="",[1,1,1,0,1,0]
L=[str(i) for i in L] # Conversion de chaque élément de L en une chaîne (string).
ch="".join(L) # méthode qui ne fonctionne qu'avec des chaînes...
print(ch)
 

Question(s) ?

@Black Jack
Ton code me chiffonne :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
            rev_L = L[::-1]
       return (rev_L)

Pourtant, ton code fonctionne aussi, je n'ai pas réussi à le prendre en défaut...
Parce que j'écrirais plutôt :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
       rev_L = L[::-1]
       return (rev_L)

@+

Bonjour,

Pour ta question finale.
Les 2 programmes ont des résultats identiques car j'ai utilisé 2 listes différentes (L et rev_L) mais tout est fait sur la liste L et le résultat final dans rev_L et celui du L final inversé

Si je n'avais utilisé qu'une seule liste L pour mettre les 0 et les 1 et la même liste pour l'auto-inverser, alors, j'aurais obligatoirement du écrire ceci.

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
       L = L[::-1]
       return (L)

n=input("entrez n :")
n=int(n)
print(binaire(n))

Dernière modification par Black Jack (03-01-2023 19:59:04)

Hors ligne

#9 03-01-2023 21:18:58

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : Système binaire sur python

Re,

Ce n'est pas ce que j'ai voulu dire : je n'aurais pas raté quelque chose d'aussi élémentaire...
Ton code :

def binaire (n) :
    L=[]
    while n >= 1 :
        r  = n%2
        n = int(n/2)
        L.append(r)
        rev_L = L[::-1]
    return (rev_L)      
 

Ma proposition donne le même résultat et ça me chiffonnait, parce que je m'y attendais pas : mais maintenant, je suis soulagé, je viens de trouver pourquoi...
En fait, tu stockes avant la fin de chaque tour, la liste L, en l'ayant renversée dans Rev_L. Mais L n'est pas touchée, c'est le contenu de L qui est renversé au moment du stockage dans Rev_L. Donc, ton indentation ou la mienne donnent le même résultat et c'est tout à fait normal...
Et parce qu'il n'y a pas renversement "en place" comme dans la suggestion du document vers lequel vani94 a mis un lien, c'est à dire L.reverse() : avec cette écriture , mon indentation est impérative, sinon le résultat serait faux...
Mon code :

def binaire (n) :
    L=[]
    while n >= 1 :
        r  = n%2
        n = int(n/2)
        L.append(r)
    rev_L = L[::-1]
    return (rev_L)
 

Si tu travaillais avec un nombre possédant plusieurs dizaines de milliers de chiffres, tu écraserais la liste Rev_L avec la nouvelle autant de fois : c'est sûrement plus lent (avec nos machines, pas sûr que ce soit perceptible), plus consommateur de ressources.
Et je trouve plus rationnel de créer une seule fois (en modifiant l'indentation de la ligne) la liste Rev_ L, juste avant de quitter la fonction...

Encore plus économique :

def binaire (n) :
       L=[]
       while n >= 1:
            L.append (n%2)
            n=n//2
       return L[::-1]

n=int(input("Entrer n : "))
print(binaire(n))
 

Sortie :

Entrer n : 654321
[1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]

Et je peux (mais c'est moins clair), sans plus de lignes, directement afficher le nombre binaire et non plus la liste :

def binaire (n) :
       L=[]
       while n >= 1:
            L.append (str(n%2))
            n=n//2
       return ("".join(L[::-1])
# N-B : join() ne fonctionne que si la liste est une liste de chaînes : d'où le str(n%2)...

n=int(input("Entrer n : "))
print(binaire(n))
 

Sortie :

Entrer n : 654321
10011111101111110001

;-)

@+

Dernière modification par yoshi (04-01-2023 10:52:32)

Hors ligne

#10 04-01-2023 13:22:16

Black Jack
Membre
Inscription : 15-12-2017
Messages : 509

Re : Système binaire sur python

"En fait, tu stockes avant la fin de chaque tour, la liste L, en l'ayant renversée dans Rev_L. Mais L n'est pas touchée, c'est le contenu de L qui est renversé au moment du stockage dans Rev_L. Donc, ton indentation ou la mienne donnent le même résultat et c'est tout à fait normal..."

Bonjour,

C'est exactement ce que j'ai essayé d'expliquer dans ma réponse #8

Hors ligne

#11 04-01-2023 17:19:06

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : Système binaire sur python

B'jour,

Désolé, j'avais mal compris (lecture trop rapide et plus ou moins en diagonale)  ton explication:
L'âge peut-être et l'heure de ma réponse : je commence l'année fatigué par mon épaule qui visiblement n'apprécie pas le couple clavier/souris, ni les changements de vitesse, ni les mouvements de torsion/rotation...

Si je n'avais utilisé qu'une seule liste L pour mettre les 0 et les 1 et la même liste pour l'auto-inverser, alors, j'aurais obligatoirement dû écrire ceci :

def binaire (n) :
       L=[]
       while n >= 1 :
            r  = n%2
            n = int(n/2)
            L.append(r)
       L = L[::-1]
       return (L)
 

Mais non, pour affichage seulement, il n'est même pas nécessaire d'écrire L=L[::-1] avant le return: il suffit d'écrire return (L[::-1]), cf mon avant-dernier code :

def binaire(n):
    L=[]
    while n >= 1:
        L.append (n%2)
        n = n//2                
    return (L[::-1])

n=int(input("Entrer n : "))
print(binaire(n))
 

Reste la question que j'avais posée de l'utilité de recréer rev_L à chaque tour de boucle, plutôt que de la créer une seule fois juste avant le return et alignée verticalement avec lui...

@+

[EDIT]

yoshi a écrit :

Par contre, si on veut la récupérer ensuite, oui il faut 2 listes...

Même pas :

def binaire(n):
    L=[]
    while n >= 1:
        L.append (n%2)
        n = n//2                
    return (L[::-1])

n=int(input("Entrer n : "))
L=binaire(n)
print(L)
 

Sortie :

Entrer n : 654321
[1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]

ou encore :

def binaire(n):
    L=[]
    while n >= 1:
        L.append (n%2)
        n = n//2
    return (L)

n=int(input("Entrer n : "))
L=binaire(n)[::-1]
print(L)
 

Sortie :

Entrer n : 654321
[1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]

voire

def binaire(n):
    L=[]
    while n >= 1:
        L.append (n%2)
        n = n//2
    L.reverse()
    return (L)

n=int(input("Entrer n : "))
L=binaire(n)
print(L)
 

Sortie :

Entrer n : 654321
[1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]

Et je peux regagner la ligne perdue en récupérant la liste retournée pour l'afficher ensuite, en passant une liste vide en paramètre :

def binaire(L,n):
    while n >= 1:
        L.append (n%2)
        n = n//2
    L.reverse()
    return (L)

n=int(input("Entrer n : "))
L=binaire([],n)
print(L)
 

Sortie :

Entrer n : 654321
[1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1]

Encore plus court :

 def binaire(L,n):
    while n >= 1:
        L.append (n%2)
        n = n//2
    return (L[::-1)

n=int(input("Entrer n : "))
L=binaire([],n)
print(L)

Dernière modification par yoshi (06-01-2023 12:10:22)

Hors ligne

Réponse rapide

Veuillez composer votre message et l'envoyer
Nom (obligatoire)

E-mail (obligatoire)

Message (obligatoire)

Programme anti-spam : Afin de lutter contre le spam, nous vous demandons de bien vouloir répondre à la question suivante. Après inscription sur le site, vous n'aurez plus à répondre à ces questions.

Quel est le résultat de l'opération suivante (donner le résultat en chiffres)?
quatre-vingt dix-huit moins cinquante quatre
Système anti-bot

Faites glisser le curseur de gauche à droite pour activer le bouton de confirmation.

Attention : Vous devez activer Javascript dans votre navigateur pour utiliser le système anti-bot.

Pied de page des forums