Aller au contenu

Ecritures des entiers

On considère le programme python suivant:

def de_caractere_vers_chiffre(caractere_chiffre):
    if caractere_chiffre == '0': return 0
    elif caractere_chiffre == '1': return 1
    elif caractere_chiffre == '2': return 2
    elif caractere_chiffre == '3': return 3
    elif caractere_chiffre == '4': return 4
    elif caractere_chiffre == '5': return 5
    elif caractere_chiffre == '6': return 6
    elif caractere_chiffre == '7': return 7
    elif caractere_chiffre == '8': return 8
    elif caractere_chiffre == '9': return 9


def de_ecritureb_vers_decimal(code_entier, base):
    """
    base: entier >= 2 (pour le moment on supposera b < 10)
    code_entier: chaîne de caractères ne contenant 
    que des symboles chiffres entre 0 et b-1

    renvoie un entier
    """
    s = 0
    for chiffre in code_entier:
        s = base*s + de_caractere_vers_chiffre(chiffre)
    return s

Ce programme associe à une chaîne de caractères-chiffres un entier.

Cette association est en fait l'association que vous utilisez naturellement en écrivant les entiers.... Détails dans ce qui suit !

Base dix

Répondre aux questions suivantes à la main (sans faire tourner le programme sur machine).

Donner les valeurs obtenues avec les appels suivants:

>>> de_ecritureb_vers_decimal('4536', 10)
>>> de_ecritureb_vers_decimal('123', 10)
>>> de_ecritureb_vers_decimal('32', 10)
4536, lecture 1

Un premier déroulement du code.

Avec l'appel

>>> de_ecritureb_vers_decimal('4536', 10)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '4536'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 10.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '4' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 0 + 4 = 4.
    • la variable chiffre prend ensuite la valeur '5' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 4 + 5 = 40+5 = 45.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times\left(45\right) + 3 = 450 + 3 = 453.
    • la variable chiffre prend ensuite la valeur '6' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times\left(453\right) + 6 = 4530 + 6 = 4536.

On obtient l'entier donné initialement par la chaîne de caractères.

4536, lecture 2

On lit à nouveau le déroulement du code mais sans effectuer les calculs intermédiaires. Cela permet de mettre en évidence les puissances de 10 successives.

Avec l'appel

>>> de_ecritureb_vers_decimal('4536', 10)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '4536'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 10.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '4' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 0 + 4 = 4.
    • la variable chiffre prend ensuite la valeur '5' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 4 + 5.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times\left(10\times 4 + 5\right) + 3.
    • la variable chiffre prend ensuite la valeur '6' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times\left[10\times\left(10\times 4 + 5\right) + 3\right] + 6.

Cette dernière valeur est la valeur renvoyée. Développons l'expression pour mieux comprendre en commençant par le couple de parenthèses le plus interne:

\begin{align} 10\times\left[10\times\left(10\times 4 + 5\right) + 3\right] + 6 &= 10\times\left[ \left(10^2\times 4 + 10\times 5\right) + 3\right] + 6 \\ &= \left[ \left(10^3\times 4 + 10^2\times 5\right) + 10\times 3 \right] + 6 \\ &= 4 \times 10^3 + 5 \times 10^2 + 3 \times 10 + 6 \\ &= 4536 \end{align}

On retrouve l'entier donné initialement. Ne pas effectuer les calculs intermédiaires permet ici de mettre en évidence que l'algorithme proposé lit le chiffre de droite comme le chiffre des unités (coefficient de 10^0), le chiffre suivant (en lecture de droite à gauche, ici 3) comme le chiffre des dizaines (coefficient de 10^1), le chiffre suivant (ici 5) comme le chiffre des centaines (coefficient de 10^2), et le suivant (ici 4) comme le chiffre des milliers (coefficient de 10^3).

123

Avec l'appel

>>> de_ecritureb_vers_decimal('123', 10)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '123'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 10.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '1' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 0 + 1 = 1.
    • la variable chiffre prend ensuite la valeur '2' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 1+ 2.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times\left(10\times 1 + 2\right) + 3.

Cette dernière valeur est la valeur renvoyée. Développons l'expression:

\begin{align} 10\times\left(10\times 1 + 2\right) + 3 &= \left(10^2\times 1 + 10\times 2\right) + 3 \\ &= 1 \times 10^2 + 2 \times 10 + 3 \ \\ &= 123 \end{align}
32

Avec l'appel

>>> de_ecritureb_vers_decimal('32", 10)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '32'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 10.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 0 + 3 = 3.
    • la variable chiffre prend ensuite la valeur '2' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 10\times 3+ 2 = 32.

Cette dernière valeur est la valeur renvoyée.

Important

Lorsque le paramètre base désigne la valeur 10, le programme transforme donc une chaîne de "caractères-chiffres" (type str) en l'entier (type int) correspondant.

L'effet est donc, dans ce cas, a priori identique à ce que l'on obtiendrait avec la fonction int prédéfinie en python.

>>> int("123")
123

Base huit

Répondre de même aux questions suivantes à la main (sans faire tourner le programme sur machine).

On notera bien que les chaînes, lorsque la base est 8, ne contiennent que des chiffres entre 0 et 7 (ce n'est pas important pour le moment dans le déroulement du programme mais ce le sera pour comprendre l'écriture en base huit).

Donner les valeurs obtenues avec les appels suivants:

>>> de_ecritureb_vers_decimal('4536', 8)
>>> de_ecritureb_vers_decimal('123', 8)
>>> de_ecritureb_vers_decimal('32', 8)
4536

On lit à nouveau le déroulement du code sans effectuer les calculs intermédiaires. On constatera cette fois que ce sont des puissances de 8 qui apparaissent dans la somme finale.

Avec l'appel

>>> de_ecritureb_vers_decimal('4536', 8)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '4536'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 8.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '4' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 0 + 4 = 4.
    • la variable chiffre prend ensuite la valeur '5' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 4 + 5.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times\left(8\times 4 + 5\right) + 3.
    • la variable chiffre prend ensuite la valeur '6' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times\left[8\times\left(8\times 4 + 5\right) + 3\right] + 6.

Cette dernière valeur est la valeur renvoyée. Développons l'expression pour mieux comprendre en commençant par le couple de parenthèses le plus interne:

\begin{align} 8\times\left[8\times\left(8\times 4 + 5\right) + 3\right] + 6 &= 8\times\left[ \left(8^2\times 4 + 8\times 5\right) + 3\right] + 6 \\ &= \left[ \left(8^3\times 4 + 8^2\times 5\right) + 8\times 3 \right] + 6 \\ &= 4 \times 8^3 + 5 \times 8^2 + 3 \times 8 + 6 \\ &= 2398 \end{align}
123

Avec l'appel

>>> de_ecritureb_vers_decimal('123', 8)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '123'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 8.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '1' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 0 + 1 = 1.
    • la variable chiffre prend ensuite la valeur '2' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 1+ 2.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times\left(8\times 1 + 2\right) + 3.

Cette dernière valeur est la valeur renvoyée. Développons l'expression:

\begin{align} 8\times\left(8\times 1 + 2\right) + 3 &= \left(8^2\times 1 + 8\times 2\right) + 3 \\ &= 1 \times 8^2 + 2 \times 8 + 3 \ \\ &= 83 \end{align}
32

Avec l'appel

>>> de_ecritureb_vers_decimal('32", 8)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '32'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 8.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 0 + 3 = 3.
    • la variable chiffre prend ensuite la valeur '2' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 8\times 3+ 2 = 26.

Cette dernière valeur est la valeur renvoyée.

Important

Nous voyons ainsi que le code "123" peut représenter l'entier 83.

Nous écrirons 123_{\text{huit}} = 83_{\text{dix}}.

Nous dirons que 123 est l'écriture en base huit de l'entier écrit usuellement 83.

L'écriture usuelle des entiers est une écriture en base 10, appelée également écriture décimale.

Ainsi 4371_{\text{huit}} = 4 \times 8^3 + 3 \times 8^2 + 7 \times 8 + 1 tandis que 4371 = 4371_{\text{dix}} = 4 \times 10^3 + 3 \times 10^2 + 7 \times 10 + 1.

Remarque

La fonction prédéfinie int dans le langage python permet de même d'obtenir à l'écran l'écriture en base dix à partir d'une écriture en base 8:

>>> int("123", 8)
83

Important

En base huit, les seuls chiffres autorisés sont les chiffres de 0 à 7 (sinon, par exemple, 81_{\text{huit}} serait égal à 8\times 8 +1 c'est à dire à 1\times 8^2 + 0\times 8 + 1 et pourrait donc aussi s'écrire 101_{\text{huit}}, et on cherche à éliminer cette possibilité de multiples écritures dans une base donnée. Nous verrons aussi dans la suite que les chiffres sont tout simplement obtenus comme des restes dans une division par 8, donc compris entre 0 et 7).

Notre fonction de_caractere_vers_chiffre, pour être plus correcte, devrait donc refuser les chiffres 8 et 9 lorsque la base est 8. C'est bien sûr le cas avec la fonction python int:

>>> int("1287", 8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 8: '1287'

Base cinq

Répondre de même aux questions suivantes à la main (sans faire tourner le programme sur machine).

En base cinq, les seuls chiffres autorisés sont 0, 1, 2, 3, 4.

  • Donner la valeur obtenue avec l' appel suivant:
>>> de_ecritureb_vers_decimal('4312', 5)
4312

On lit à nouveau le déroulement du code sans effectuer les calculs intermédiaires. On constatera cette fois que ce sont des puissances de 5 qui apparaissent dans la somme finale.

Avec l'appel

>>> de_ecritureb_vers_decimal('4312', 5)
  • une variable code_entier, locale à la fonction, est créée, et cette variable désigne la valeur de type str '4312'.
  • une variable base, locale à la fonction, est créée, et cette variable désigne la valeur de type int 5.
  • une variable s, locale à la fonction, est créée, et cette variable désigne la valeur de type int 0.
  • On commence ensuite la boucle for:
    • la variable chiffre prend la valeur '4' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 5\times 0 + 4 = 4.
    • la variable chiffre prend ensuite la valeur '3' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 5\times 4 + 3.
    • la variable chiffre prend ensuite la valeur '1' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 5\times\left(5\times 4 + 3\right) + 1.
    • la variable chiffre prend ensuite la valeur '2' puis la variable s prend la valeur base*s + de_caractere_vers_chiffre(chiffre), soit 5\times\left[5\times\left(5\times 4 + 3\right) + 1\right] + 2.

Cette dernière valeur est la valeur renvoyée. Développons l'expression pour mieux comprendre en commençant par le couple de parenthèses le plus interne:

\begin{align} 5\times\left[5\times\left(5\times 4 + 3\right) + 1\right] + 2 &= 5\times\left[ \left(5^2\times 4 + 5\times 3\right) + 1\right] + 2 \\ &= \left[ \left(5^3\times 4 + 5^2\times 3\right) + 5\times 1 \right] + 2 \\ &= 4 \times 5^3 + 3 \times 5^2 + 1 \times 5 + 2 \\ &= 582 \end{align}
  • Donner l'écriture en base dix de 123_{\text{cinq}}.
123

Avec l'appel

>>> de_ecritureb_vers_decimal('123', 5)
38

Avec int:

>>> int("123", 5)
38

et à la main:

123_{\text{cinq}} = 1\times 5^2 + 2 \times 5 + 3 = 38.

  • Donner l'écriture en base dix de 32_{\text{cinq}}.
32

Avec le programme:

>>> de_ecritureb_vers_decimal('32", 5)
17

Avec la fonction int de python:

>>> int("32", 5)
17

et à la main:

32_{\text{cinq}} = 3 \times 5 + 2 = 17.

Base deux

En base deux, les seuls chiffres autorisés sont les chiffres 0 et 1.

Donner l'écriture en base dix des entiers suivants:

  • a = 101_{\text{deux}}
  • b = 10_{\text{deux}}
  • c = 1110_{\text{deux}}
101

Avec notre fonction ou avec int :

>>> de_ecritureb_vers_decimal("101",2)
5
>>> int("101", 2)
5

Et à la main:

a = 101_{\text{deux}} = 1\times 2^2 + 0 \times 2 + 1 = 5

10

Avec notre fonction ou avec int :

>>> de_ecritureb_vers_decimal("10",2)
2
>>> int("10", 2)
2

Et à la main:

b = 10_{\text{deux}} = 1\times 2 + 0 = 2.

1110

Avec notre fonction ou avec int :

>>> de_ecritureb_vers_decimal("1110", 2)
14
>>> int("1110", 2)
14

Et à la main:

c = 1110_{\text{deux}} = 1\times 2^3 + 1\times 2^2 + 1\times 2 + 0 = 14.

Exercice

Nous avons signalé qu'en base b (on suppose ici 2\leqslant b \leqslant 9), les chiffres autorisés sont les chiffres de 0 à b-1.

Ajoutez une instruction assert dans le script précédent afin que l'utilisateur soit prévenu lorsqu'il utilise un symbole non autorisé.

Solution

Un code possible:

def de_caractere_vers_chiffre(caractere_chiffre):
    if caractere_chiffre == '0': return 0
    elif caractere_chiffre == '1': return 1
    elif caractere_chiffre == '2': return 2
    elif caractere_chiffre == '3': return 3
    elif caractere_chiffre == '4': return 4
    elif caractere_chiffre == '5': return 5
    elif caractere_chiffre == '6': return 6
    elif caractere_chiffre == '7': return 7
    elif caractere_chiffre == '8': return 8
    elif caractere_chiffre == '9': return 9


def de_ecritureb_vers_decimal(code_entier, base):
    """
    base: entier >= 2 (pour le moment on supposera b < 10)
    code_entier: chaîne de caractères ne contenant 
    que des symboles chiffres entre 0 et b-1

    renvoie un entier
    """
    s = 0
    for chiffre in code_entier: 
        assert de_caractere_vers_chiffre(chiffre) in range(0, base), \
        f"Attention, en base {base}, le symbole {chiffre} n'est pas autorisé."
        s = base*s + de_caractere_vers_chiffre(chiffre)
    return s