web-dev-qa-db-fra.com

Est-il possible de différencier entre 0 et -0?

Je sais que les valeurs entières 0 et -0 sont essentiellement les mêmes. Mais je me demande s'il est possible de les différencier.

Par exemple, comment savoir si une variable a été affectée -0?

bool IsNegative(int num)
{
    // How ?
}

int num = -0;
int additinon = 5;

num += (IsNegative(num)) ? -addition : addition;

Est la valeur -0 enregistré dans la mémoire exactement de la même manière que 0?

92
Filip Minx

Cela dépend de la machine que vous ciblez.

Sur une machine qui utilise une représentation du complément à 2 pour les entiers, il n'y a aucune différence au niveau du bit entre 0 et -0 (ils ont la même représentation)

Si votre machine utilisait son complément , vous pourriez certainement

0000 0000   -> signed   0 
1111 1111   -> signed   −0

Évidemment, nous parlons d'utiliser le support natif , les processeurs de la série x86 ont un support natif pour la représentation du complément à deux des nombres signés. L'utilisation d'autres représentations est certainement possible mais serait probablement moins efficace et nécessiterait plus d'instructions.

(Comme JerryCoffin l'a également noté: même si son complément a été considéré principalement pour des raisons historiques, les représentations de magnitude signées sont encore assez courantes et ont une représentation distincte pour le zéro négatif et le zéro positif)

112
Marco A.

Pour un int (dans la représentation presque universelle du "complément à 2"), les représentations de 0 et -0 sont identiques. (Ils peuvent être différents pour d'autres représentations numériques, par exemple, virgule flottante IEEE 754.)

14
RichieHindle

Commençons par représenter le complément de 0 dans 2 (bien sûr, il existe de nombreux autres systèmes et représentations, ici je fais référence à celui-ci), en supposant que 8 bits, zéro est:

0000 0000

Maintenant, retournons tous les bits et ajoutons 1 pour obtenir le complément de 2:

1111 1111 (flip)
0000 0001 (add one)
---------
0000 0000

nous avons 0000 0000, et c'est aussi la représentation de -0.

Mais notez que dans le complément de 1, signé 0 est 0000 0000, mais -0 est 1111 1111.

12
Maroun

J'ai décidé de laisser cette réponse en place car les implémentations C et C++ sont généralement étroitement liées, mais en fait, elle ne s'en remet pas au standard C comme je le pensais. Le fait demeure que la norme C++ ne spécifie pas ce qui se passe pour des cas comme ceux-ci. Il est également pertinent de noter que les représentations sans complément à deux sont extrêmement rares dans le monde réel, et que même lorsqu'elles existent, elles cachent souvent la différence dans de nombreux cas plutôt que de l'exposer comme quelque chose que quelqu'un pourrait facilement s'attendre à découvrir.


Le comportement des zéros négatifs dans les représentations entières dans lesquelles ils existent n'est pas défini aussi rigoureusement dans la norme C++ que dans la norme C. Il cite cependant la norme C (ISO/CEI 9899: 1999) comme référence normative au niveau supérieur [1.2].

Dans la norme C [6.2.6.2], un zéro négatif ne peut être que le résultat d'opérations au niveau du bit, ou d'opérations où un zéro négatif est déjà présent (par exemple, multiplier ou diviser un zéro négatif par une valeur, ou ajouter un zéro négatif à zéro) - l'application de l'opérateur unaire moins à une valeur de zéro normal, comme dans votre exemple, garantit donc un zéro normal.

Même dans les cas où peut générer un zéro négatif, il n'y a aucune garantie qu'ils le feront, même sur un système qui prend en charge le zéro négatif:

Il n'est pas précisé si ces cas génèrent réellement un zéro négatif ou un zéro normal, et si un zéro négatif devient un zéro normal lorsqu'il est stocké dans un objet.

Par conséquent, nous pouvons conclure: non, il n'y a aucun moyen fiable de détecter ce cas. Même si ce n'est pas pour le fait que les représentations non complémentaires à deux sont très rares dans les systèmes informatiques modernes.

La norme C++, quant à elle, ne fait aucune mention du terme "zéro négatif", et a très peu de discussion sur les détails de la grandeur signée et des représentations de son complément, sauf pour noter [3.9.1 paragraphe 7] qu'elles sont autorisées.

9
Random832

Si votre machine a des représentations distinctes pour -0 et +0, puis memcmp pourra les distinguer.

Si des bits de remplissage sont présents, il peut également y avoir plusieurs représentations de valeurs autres que zéro.

8
Ben Voigt

Dans la spécification du langage C++, il n'y a pas d'int entier tel que zéro négatif.

La seule signification de ces deux mots est l'opérateur unaire - appliqué à 0, tout comme trois plus cinq est juste l'opérateur binaire + appliqué à 3 et 5.

S'il y avait un zéro négatif distinct, le complément à deux (la représentation la plus courante des types entiers) serait une représentation insuffisante pour les implémentations C++, car il n'y a aucun moyen de représenter deux formes de zéro.


En revanche, les virgules flottantes (suivant l'IEEE) ont des zéros positifs et négatifs séparés. Ils peuvent être distingués, par exemple, en divisant 1 par eux. Le zéro positif produit l'infini positif; un zéro négatif produit un infini négatif.


Cependant, s'il se trouve qu'il existe différentes représentations en mémoire de l'int 0 (ou de tout int, ou de toute autre valeur de tout autre type), vous pouvez utiliser memcmp pour découvrir que:

#include <string>

int main() {
    int a = ...
    int b = ...
    if (memcmp(&a, &b, sizeof(int))) {
        // a and b have different representations in memory
    }
}

Bien sûr, si cela se produisait, en dehors des opérations de mémoire directe, les deux valeurs fonctionneraient toujours exactement de la même manière.

5
Paul Draper

Pour simplifier, j'ai trouvé plus facile à visualiser.

Le type int (_ 32) est stocké avec 32 bits . 32 bits signifie 2 ^ 32 = 4294967296 valeurs uniques . Ainsi :

la plage de données int non signée est 0 à 4 294 967 295

En cas de valeurs négatives, cela dépend de la façon dont elles sont stockées. Au cas où

Dans le cas de Le complément à un la valeur -0 existe.

2
Margus