J'avais étudié l'algorithme pour trouver des entiers solitaires dans un tableau, et voici l'implémentation:
int arr[] = {10, 20, 30, 5, 20, 10, 30};
int LonelyInteger = 0;
for(int i=0; i< 7; i++)
{
LonelyInteger = LonelyInteger ^ arr[i];
}
Le résultat est 5
.
Ma question est - supposément les entiers (générés par l'opération XOR
) sont trop grands à cause de cette opération:
LonelyInteger ^ arr[i]
Ce qui conduit à un entier potentiellement grand qui ne peut pas être représenté par le type de données disons int
dans ce cas. Mes questions sont:
XOR
génère une valeur entière aussi grande qui ne peut pas être stockée dans le type int
?XOR
ne sortira jamais des limites car il combine des bits et ne crée pas de nouveaux bits là où aucun bit n'était défini auparavant.
Le résultat 5
est correct. Regardez la représentation binaire de votre valeur et le résultat XOR
10 00001010
20 00010100
30 00011110
5 00000101
20 00010100
10 00001010
30 00011110
--------------
00000101 => 5
Une aide simple pour calculer un résultat de nombreuses valeurs XOR
ed est: Le résultat aura un ensemble de bits où un nombre impair de bits est combiné, aucun ensemble de bits pour un nombre pair de bits.
S'il n'est pas possible que cela se produise, y a-t-il une preuve à cela?
XOR
est équivalent à l'addition sans report sur les bits individuels. Lorsque vous ajoutez des bits sans report, aucun débordement ne peut se produire et la valeur int
ne peut donc pas sortir des limites.
Le résultat ne peut jamais être "trop grand" dans le sens où sa représentation nécessite plus de bits que int
fournit, puisque l'opération est définie pour combiner les valeurs de bits de ses opérandes, ne pas produire de nouveaux bits. Peut-être qu'une meilleure question pourrait être, le résultat peut-il être autre chose qu'une représentation de valeur valide d'un int
?
Pour les entiers non signés, non. Tous les modèles de bits, et donc le résultat de toutes les opérations au niveau du bit, sont des représentations de valeurs valides.
Pour les entiers signés, cela dépend de la représentation définie par l'implémentation des valeurs négatives. Chaque implémentation que vous êtes susceptible de rencontrer utilise le complément à 2, dans lequel chaque modèle de bits est à nouveau valide; là encore, le résultat de toute opération au niveau du bit sera une représentation valide.
Cependant, la norme autorise également d'autres représentations, dans lesquelles il peut y avoir un ou plusieurs motifs binaires invalides. Dans ce cas, il est possible qu'une opération au niveau du bit, avec deux opérandes valides, produise ce modèle, et donc produise un résultat invalide.
(Ce message s'applique au C, pas au C++)
Les opérateurs au niveau du bit ne peuvent pas provoquer une représentation d'interruption en raison de la définition de bits de remplissage non valides, voir la note de bas de page C11 6.2.6.2/1:
... aucune opération arithmétique sur des valeurs valides ne peut générer une représentation d'interruption ...
(La signification de "opération arithmétique" n'est pas claire mais l'index est lié au 6.5.11 qui est la définition de XOR).
Cependant, en C, ils peuvent provoquer la génération d'un zéro négatif . Dans le complément de 2, il n'y a pas de zéro négatif. Mais disons que vous étiez sur un système avec un complément à 1, vous pourriez générer un zéro négatif via ^
et cela pourrait provoquer une représentation d'interruption. 6.2.6.2/3 dit explicitement que cela est possible:
Si la mise en œuvre prend en charge des zéros négatifs, ils ne doivent être générés que par:
- les opérateurs &, |, ^, ~, << et >> avec des opérandes qui produisent une telle valeur;
Enfin 6.2.6.2/2 implique (je suis sûr de toute façon) qu'il n'est pas possible d'avoir une combinaison de bits de valeur qui représenterait un entier dépassant INT_MAX
Pour résumer, les résultats possibles de ^
sur deux int
sont:
int
valide (peut-être avec des bits de remplissage différents mais non-piégés vers d'autres versions de la même valeur)Strictement parlant, vous ne pouvez pas XOR deux entiers. Vous pouvez XOR deux sacs de bits de taille entière, et vous pouvez Traitez ces sacs de bits comme des entiers à d'autres moments. Vous pouvez même les traiter comme des entiers à tous les autres fois.
Mais au moment où vous effectuez l'opération XOR, vous les traitez comme quelque chose de très différent des entiers, ou même des nombres, en soi : ce ne sont que deux séquences de bits, où les bits correspondants sont comparés. Le concept de débordement ne s'applique pas à cela, et donc si vous décidez de traiter le résultat comme un entier, il ne peut pas non plus déborder.
Est-il même possible que XOR génère une valeur entière aussi grande qui ne peut pas être stockée dans le type int?
Si les opérandes sont int
, alors non.
S'il n'est pas possible que cela se produise, y a-t-il une preuve à cela?
Eh bien, c'est trivial d'après la définition. Ce n'est pas une preuve mathématiquement rigoureuse, mais vous pourriez considérer qu'un bit dans la sortie de XOR ne sera égal à 1 que si l'un des opérandes en a 1 dans cette position. Comme un bit hors plage ne peut pas être 1 dans les opérandes, il n'y a pas de bit de sortie avec la valeur 1 qui est hors plage.
XOR, AND, OR, NOT et tout autre opérateur au niveau du bit produisent des résultats au niveau du bit, les bits du résultat étant combinés à partir des bits exactement à la même position dans les entrées. Ainsi, les entrées à n bits produisent n bits sans bit supérieur, alors comment peut-il sortir des limites?
Non ça ne peut pas. Contrairement à d'autres réponses, la mienne serait une preuve mathématique.
XOR
est un raccourci pour exclusif o ou disjonction exclusive (⊕
) et peut être défini comme:
A ⊕ B = (A ∪ B)\(A ∩ B)
Votre thèse est que
∃x: x ∉ A ∧ x ∉ B ∧ x ∈ (A ⊕ B)
Donc, à partir de la première équation
x ∈ (A ∪ B)\(A ∩ B)
Que peut-on exprimer
x ∈ (A ∪ B) ∧ x ∉ (A ∩ B)
La deuxième partie peut être exprimée comme suit:
x ∉ A ∧ x ∉ B
La première partie peut être exprimée comme suit:
x ∈ A ∨ x ∈ B
De quoi entrer en collision avec notre hypothèse que x ∉ A ∧ x ∉ B
donc la thèse est fausse pour tout ensemble A
et B
.
Q.E.D.
Dans un CAS GÉNÉRAL l'algorithme décrit ne peut pas vraiment trouver un entier solitaire dans un tableau. Ce qu'il trouve vraiment, c'est XOR
de tous les éléments qui s'y produisent un nombre impair.
Donc, s'il n'y a qu'un seul élément "solitaire", dites un élément 'a'
, Et tous les autres éléments se produisent MÊME fois dans le tableau, alors cela fonctionne "comme requis" -> il trouve cet élément solitaire 'a'
.
Pourquoi?
L'algorithme exécute XOR
de tous les éléments du tableau (a ^ b ^ c ^ d ^ ...)
L'opération XOR
a les propriétés suivantes:
1) a ^ a = 0 (non-equivalence)
2) a ^ 0 = a (neutrality of 0)
3) a ^ b = b ^ a (commutative property)
4) (a ^ b) ^ c = a ^ (b ^ c) (associative property)
Supposons, par exemple, un tableau avec des éléments: {a, b, c, a, c, b, a, c}
(élément 'a'
- 3 fois, élément 'b'
- deux fois, élément 'c'
- 3 fois)
Ensuite, selon les propriétés XOR
mentionnées ci-dessus, le résultat de l'algorithme
R = (((((((a ^ b) ^ c) ^ a) ^ c) ^ b) ^ a) ^ c)
peut être réorganisé comme suit:
R = (a ^ b) ^ (c ^ a) ^ (c ^ b) ^ (a ^ c) =
= (a ^ a) ^ (b ^ b) ^ (c ^ c) ^ (a ^ c) =
= 0 ^ 0 ^ 0 ^ (a ^ c) = (a ^ c)
c'est à dire.,
a) ...tous les éléments qui se produisent même un nombre de fois donnent zéro
b) ...tous les éléments qui se produisent un ODD nombre de fois sont XOR-ed et créent le résultat final
XOR
est une opération bit par bit, donc elle ne peut jamais déborder, bien sûr.
Supposer
int xor = x^y;
Max value of int is x = 999999999;
Max value of Xor will come if y=0;
and Max Xor is 999999999;
ce qui est en limite. :)
Est-il même possible que XOR génère une valeur entière aussi grande qui ne peut pas être stockée dans le type int?
Data-Type3 = Data-Type1 operator Data-Type2
S'il n'est pas possible que cela se produise, y a-t-il une preuve à cela?
Nous avons Data-Type3
dans le cas d'Integers est celui sur Data-Type1
et Data-Type2
qui a une plus grande taille, même en cas d'addition ou de multiplication.
SIZE(Data-Type3) = MAX(SIZE(Data-Type1), SIZE(Data-Type2))
Donc si Data-Type1 = Data-Type2
alors c'est aussi le type de retour.
Short + Short = Short
Short + Integer = Integer
Short + Long = Long
Integer + Short = Integer
Integer + Integer = Integer
Integer + Long = Long
Long + Short = Long
Long + Integer = Long
Long + Long = Long
Ce qui peut arriver est un débordement, qui peut se produire lorsqu'une opération a un report. Dans le complément à 2, c'est lorsque le report dans la colonne d'ordre supérieur n'est pas égal au report de la colonne d'ordre supérieur. en savoir plus
Mais l'opération XOR ne peut pas déborder , car XOR ne génère pas de report, car XOR est une opération bit à bit comme NOT.