Usage de ~ qui, ce me semble, veut dire not.

Le
Dominique
Bonjour,

Python 3.8.5.

Je comprends mal le comportement de ~ (le tilde) :

soit a,b=5,7

a>b False normal

a>~b True, résultat attendu

b<a False, normal, mais

b<~a False aussi, et lÍ , je ne comprends pas. Voyez-vous pourquoi j'ai
ce résultat inattendu ? Je suppose que, Í  la question « b pas inférieur
Í  a », je devrais obtenir True

En vous souhaitant un beau dimanche,

--
Dominique
Courriel : dominique point sextant ate orange en France
Esto quod es
  • Partager ce contenu :
Vos réponses Page 1 / 2
Trier par : date / pertinence
Dominique
Le #26571668
Le 11/04/2021 Í  10:57, Dominique a écrit :
Bonjour,
Python 3.8.5.
Je comprends mal le comportement de ~ (le tilde) :
soit a,b=5,7
a>b False normal
a>~b True, résultat attendu
b<a False, normal, mais
b<~a False aussi, et lÍ , je ne comprends pas. Voyez-vous pourquoi j'ai
ce résultat inattendu ? Je suppose que, Í  la question « b pas inférieur
Í  a », je devrais obtenir True...
En vous souhaitant un beau dimanche,


Bon, mon fils m'a apporté une explication que je ne comprends pas bien
mais je vois que not a==0 rend True, quelle que soit la valeur de a. Je
déduis que « not une variable » retourne toujours 0, or 0 est False.
Mais si x='' (string vide), not x donne True. pourquoi ?
Pour revenir au tilde, soit a=5, ~a donne -6 et ~-5 donne 4... Pourquoi
? On voit comme un effet miroir avec une réduction de la valeur relative
d'une unité (~5 donne -5-1 et ~-6 donne 6-1)...
Tout ceci me rend perplexe :-)
--
Dominique
Courriel : dominique point sextant ate orange en France
Esto quod es
Benoit Izac
Le #26571670
Bonjour,
Le 11/04/2021 Í  10:57, Dominique a écrit dans le message
Je comprends mal le comportement de ~ (le tilde) :
[ce me semble, veut dire not.]

Inexact :
«Â not » c'est… «Â not ».
--
Benoit Izac
Benoit Izac
Le #26571669
Bonjour,
Le 11/04/2021 Í  11:36, Dominique a écrit dans le message
Bon, mon fils m'a apporté une explication que je ne comprends pas bien
mais je vois que not a==0 rend True, quelle que soit la valeur de a.

Pas tout ͠ fait vrai :
a = 0
not a==0



False
False==0



True
--
Benoit Izac
Alain Ketterlin
Le #26571674
Dominique
Je comprends mal le comportement de ~ (le tilde) :
soit a,b=5,7
a>b False normal
a>~b True, résultat attendu
b<a False, normal, mais
b<~a False aussi, et lÍ , je ne comprends pas. Voyez-vous pourquoi
j'ai ce résultat inattendu ? Je suppose que, Í  la question « b pas
inférieur Í  a », je devrais obtenir True...


[...]
Bon, mon fils m'a apporté une explication que je ne comprends pas bien
mais je vois que not a==0 rend True, quelle que soit la valeur de a.

Ben non, si a vaut 0, "not a == 0" vaut False.
Je déduis que « not une variable » retourne toujours 0, or 0 est
False.

Hmmm. Il n'y a rien de tel. "not" est la négation booléenne (qui change
True and False et vice-versa). Son opérande devrait en toute rigueur
être toujours une valeur booléenne.
Mais si x='' (string vide), not x donne True. pourquoi ?

Normalement "not" s'applique Í  un booléen (comme "a == 0"), donc quand
on applique "not" Í  autre chose, le choix a été fait de transformer
cette autre chose en booléen. Cela n'a aucune signification universelle,
c'est juste une commodité, avec des conventions plus ou moins
arbitraire. En gros, "not x" vaut :
- si x est None, il est considéré avoir la valeur booléenne False (donc
"not None" vaut True)
- si x est un entier, la valeur 0 est False et toute autre valeur est
True ; donc "not x" équivaut Í  "x == 0"
- si x est une chaÍ®ne de caractères, la valeur vide '' vaut False et
toute autre valeur vaut True ; donc "not x" équivaut Í  "len(x) == 0"
etc.
Les détails sont Í 
https://docs.python.org/3/reference/expressions.html#comparisons
Tout ça pout économiser quelques caractères...
Pour revenir au tilde, soit a=5, ~a donne -6 et ~-5 donne 4...
Pourquoi ? On voit comme un effet miroir avec une réduction de la
valeur relative d'une unité (~5 donne -5-1 et ~-6 donne 6-1)...

Le tilde est l'opération de négation bit-Í -bit (*pas* la négation
booléenne, une sorte de micro-négation appliquée ndividuellement sur les
bits qui composent une valeur). Elle change chaque bit en son
complément. Ce que tu oberves est le résultat de l'opération appliquée Í 
des données qui représentent des entiers. C'est lié au codage des
entiers en "complément Í  deux". Cf. par exemple (plutÍ´t la page en
anglais) :
https://fr.wikipedia.org/wiki/Compl%C3%A9ment_%C3%A0_deux
https://en.wikipedia.org/wiki/Two%27s_complement
Et effectivement, ~x est égal Í  -(x+1). C'est une propriété de cette
représentation (~0 -> -1, ~1 -> -2, etc.), mais c'est une propriété
arithmétique, disons, anecdotique : l'opération ~ inverse
individuellement les bits de l'entier, c'est tout. Il existe des
microprocesseurs utilisant une autre représentation et cette propriété
n'est pas vraie sur ces processeurs.
Pour comprendre ce qui se passe, il faut se souvenir que les entiers
sont représentés sur un nombre fini de bits (en général 32 ou 64), et
que tous les bits sont inversés. Par exemple, sur 32 bits :
5 est représenté par 0...0101 (32 bits en tout, donc 29 fois 0 en tête).
~5 est donc 1...1010 (avec donc 29 fois 1 en tête)
Et 1...1010 c'est la représentation de -6.
(En python, le nombre de bits pour représenter un entier n'est pas fixé,
mais c'est une autre histoire et ça ne change rien Í  notre propos. Tu
peux imaginer qu'il y a toujours quelques zéros en tête d'une valeur
positive -- et quelques uns en tête d'une valeur négative.)
Le tilde n'est utile que quand on travaille sur des bits individuels
(qu'on regroupe en général dans des entiers, parce qu'on n'a pas mieux).
Les autres opérations apparentées sont & | ^ (autres opérations binaires
bit-Í -bit : "and" "or" "xor"), ainsi que << et >> (décalages). Exercice
pour le lecteur : pourquoi est-ce que "-1 >> d" vaut -1 quelle que soit
la valeur de d ?
-- Alain.
Olivier Miakinen
Le #26571679
Bonjour,
Je viens Í  peine de me mettre au python (il y a en gros une ou deux
semaines), alors ce genre de question m'intéresse beaucoup :
Le 11/04/2021 12:47, Alain Ketterlin a écrit :
[...]
Les autres opérations apparentées sont & | ^ (autres opérations binaires
bit-Í -bit : "and" "or" "xor"), ainsi que << et >> (décalages). Exercice
pour le lecteur : pourquoi est-ce que "-1 >> d" vaut -1 quelle que soit
la valeur de d ?

Je suppose que le décalage Í  droite propage le bit de signe, afin que
"-6 >> 1" vaille 3 tout comme "6 >> 1" vaut 3. Mais existe-t-il un type
d'entier non signé ? Un truc qui ferait que "unsigned(-1)" vaudrait un
de moins qu'une grande puissance de 2 ?
--
Olivier Miakinen
Benoit Izac
Le #26571678
Bonjour,
Le 11/04/2021 Í  13:53, Olivier Miakinen a écrit dans le message
Les autres opérations apparentées sont & | ^ (autres opérations binaires
bit-Í -bit : "and" "or" "xor"), ainsi que << et >> (décalages). Exercice
pour le lecteur : pourquoi est-ce que "-1 >> d" vaut -1 quelle que soit
la valeur de d ?

Je suppose que le décalage Í  droite propage le bit de signe, afin que
"-6 >> 1" vaille 3 tout comme "6 >> 1" vaut 3. Mais existe-t-il un type

^
-3
d'entier non signé ? Un truc qui ferait que "unsigned(-1)" vaudrait un
de moins qu'une grande puissance de 2 ?

Moi je pense que «Â a >> 1 == ~(~a >> 1) » donc vu que «Â -1 == ~0 » et
que «Â 0 >> d » vaut toujours 0, «Â ~(~0 >> d) == -1 ».
--
Benoit Izac
Olivier Miakinen
Le #26571680
Le 11/04/2021 14:03, Benoit Izac m'a répondu :
Les autres opérations apparentées sont & | ^ (autres opérations binaires
bit-Í -bit : "and" "or" "xor"), ainsi que << et >> (décalages). Exercice
pour le lecteur : pourquoi est-ce que "-1 >> d" vaut -1 quelle que soit
la valeur de d ?

Je suppose que le décalage Í  droite propage le bit de signe, afin que
"-6 >> 1" vaille 3 tout comme "6 >> 1" vaut 3. Mais existe-t-il un type

^
-3

Oui, bien sÍ»r. Faute de frappe stupide vu le peu de texte que j'écrivais :
j'aurais dÍ» me relire.
d'entier non signé ? Un truc qui ferait que "unsigned(-1)" vaudrait un
de moins qu'une grande puissance de 2 ?

Moi je pense que «Â a >> 1 == ~(~a >> 1) »

Certes, mais c'est une *conséquence* du fait que le décalage Í  droite propage
le bit de signe. J'ai du mal Í  voir ça comme une cause ou une explication de
ce comportement.
Par exemple, ça ne fonctionne Í  priori jamais avec le décalage Í  gauche :
« a << 1 != ~(~a << 1) »
Enfin, ça ne répond pas Í  ma question : y a-t-il un type unsigned en python ?
--
Olivier Miakinen
Benoit Izac
Le #26571682
Bonjour,
Le 11/04/2021 Í  14:39, Olivier Miakinen a écrit dans le message
Enfin, ça ne répond pas Í  ma question : y a-t-il un type unsigned en
python ?

Ça s'est facile : non.
--
Benoit Izac
Olivier Miakinen
Le #26571685
Le 11/04/2021 14:57, Benoit Izac a écrit :
Enfin, ça ne répond pas Í  ma question : y a-t-il un type unsigned en
python ?

Ça c'est facile : non.

:-)
Ok, je dois dire que je m'en doutais un peu. D'un autre cÍ´té, ça me semble
assez peu utile si les entiers sont au moins sur 64 bits.
--
Olivier Miakinen
Alain Ketterlin
Le #26571686
Olivier Miakinen
Les autres opérations apparentées sont & | ^ (autres opérations binaires
bit-Í -bit : "and" "or" "xor"), ainsi que << et >> (décalages). Exercice
pour le lecteur : pourquoi est-ce que "-1 >> d" vaut -1 quelle que soit
la valeur de d ?

Je suppose que le décalage Í  droite propage le bit de signe, afin que
"-6 >> 1" vaille 3 tout comme "6 >> 1" vaut 3. Mais existe-t-il un type
d'entier non signé ? Un truc qui ferait que "unsigned(-1)" vaudrait un
de moins qu'une grande puissance de 2 ?

Ton explication est correcte : en Python tous les entiers sont signés,
et tous les décalages "Í  droite" s'effectuent avec "extension de signe"
(le bit le plus Í  droite est répliqué). Dans -1 tous les bits sont Í  1,
et donc le restent lors du décalage.
(Juste un truc, pour être sÍ»r : le "bit de signe" est une expression
correcte -- le bit de poids fort, le plus Í  gauche, est effectivement 1
pour les entiers négatifs -- mais il vaut mieux éviter les confusions
avec la représentation "signed-magnitude", celle qui a deux
représentations de zéro.)
Et non, il n'y a pas d'entiers non signés en Python, ce qui n'a pas
vraiment de conséquence pratique, puisque tous les entiers sont de
précision arbitraire. Si on utilise uniquement des entiers positifs et
qu'on effectue des décalages, le résultat restera toujours positif, on
ne risque pas de surprise. Pour avoir 2^n-1 on fait "2 ** n - 1". Note
que la définition du langage précise :
"A right shift by n bits is defined as floor division by pow(2,n). A
left shift by n bits is defined as multiplication with pow(2,n)."
Au passage, puisqu'on parlait de ~ la doc dit :
"The unary ~ (invert) operator yields the bitwise inversion of its
integer argument. The bitwise inversion of x is defined as -(x+1). It
only applies to integral numbers."
Tout cela dans : https://docs.python.org/3/reference/expressions.html --
et si vous trouvez bizarre qu'on "réduise" les opérations binaires Í  des
opérations arithmétiques, vous avez toute ma sympathie.
Enfin, pour ceux que la discussion rend perplexe : il y a deux façons de
décaler Í  droite. Le décalage "arithmétique" recopie le bit de poids
fort, le décalage "logique" le met Í  zéro (ce sont respectivement les
instructions SAR et SHR sur x86). En C (entre autres), on utilise l'une
ou l'autre selon le type de l'entier. Ainsi :
x = -1;
y = x >> 1;
donnera Í  y une valeur différente selon que x est signé ou pas.
Rien de tout cela en Python : tout est signé, le décalage est toujours
arithmétique, il n'y a pas d'overflow, division et modulo sont corrects,
etc. C'est reposant, tant qu'on ne s'occupe pas de performance ou
d'occupation mémoire.
-- Alain.
Poster une réponse
Anonyme