Zéro négatif en C

Bonjour, je suis en train d’apprendre Objective C et je faisais l’exemple de la calculasortingce classique.

Le problème est que je reçois un zéro négatif lorsque je le multiplie par un nombre négatif et que je mets le résultat dans un type (double)!

Pour voir ce qui se passait, j’ai joué avec le débogueur et voici ce que j’ai obtenu:

(gdb) print -2 * 0
1 $ = 0

(gdb) print (double) -2 * 0
2 $ = -0

Dans le second cas, lorsque je le transforme en un type double, il se transforme en zéro négatif! Comment puis-je résoudre ce problème dans mon application? J’ai besoin de travailler avec des doubles. Comment puis-je corriger le résultat afin d’obtenir un zéro alors que le résultat devrait être nul?

Merci d’avance.

J’ai fait un test simple:

 double d = (double) -2.0 * 0; if (d < 0) printf("d is less than zero\n"); if (d == 0) printf("d is equal to zero\n"); if (d > 0) printf("d is greater than zero\n"); printf("d is: %lf\n", d); 

Il produit:

d est égal à zéro
d est: -0.000000

Donc, pour résoudre ce problème, vous pouvez append un simple if-check à votre application:

 if (d == 0) d = 0; 

http://en.wikipedia.org/wiki/Signed_zero

Le nombre 0 est généralement codé +0, mais peut être représenté par +0 ou -0.

Cela ne devrait pas avoir d’impact sur les calculs ou la sortie de l’interface utilisateur.

Il y a un malentendu ici sur la priorité des opérateurs:

 (double) -2 * 0 

est analysé comme

 ((double)(-(2))) * 0 

qui est essentiellement identique à (-2.0) * 0.0 .

L’Annexe J informative C standard indique comme comportement Unspecifier si certains opérateurs peuvent générer des zéros négatifs et si un zéro négatif devient un zéro normal lorsqu’il est stocké dans un object (6.2.6.2).

Inversement, (double)(-2 * 0) devrait générer un zéro positif 0.0 sur la plupart des plateformes actuelles, car la multiplication est effectuée à l’aide de l’arithmétique entière. La norme C prend en charge les architectures qui distinguent les entiers zéro positif et négatif, mais celles-ci sont extrêmement rares de nos jours.

Si vous voulez forcer les zéros à être positifs, cette solution simple devrait fonctionner:

 if (d == 0) { d = 0; } 

Vous pouvez clarifier l’intention avec ceci:

 if (d == -0.0) { d = +0.0; } 

Mais le test réussira aussi si d est un zéro positif.

Chux propose une solution plus simple pour les environnements conformes à la norme IEC 60559:

 d = d + 0.0; // turn -0.0 to +0.0 

Comment puis-je résoudre ce problème dans mon application?

Le code n’est vraiment pas cassé, donc rien ne doit être “corrigé”. @kennytm

Comment puis-je corriger le résultat afin d’obtenir un zéro alors que le résultat devrait être nul?

Pour vous débarrasser facilement de - lorsque le résultat est -0.0 , ajoutez 0.0 . Le code suivant les règles standard (virgule flottante CEI 60559) produira un abandon du signe - .

 double nzero = -0.0; printf("%f\n", nzero); printf("%f\n", nzero + 0.0); printf("%f\n", fabs(nzero)); // This has a side effect of changing all negative values // pedantic code using  if (signbit(nzero)) nzero = 0.0; // This has a side effect of changing all negative values printf("%f\n", nzero); 

Sortie habituelle.

 -0.000000 0.000000 0.000000 0.000000 

Pourtant, pour le double x général qui peut avoir n’importe quelle valeur, il est difficile de battre le suivant @Richard J. Ross III @chqrlie L’approche x + 0.0 présente l’avantage de ne pas introduire de twig, mais ce qui suit est clair.

 if (x == 0.0) x = 0.0; 

Remarque: fmax(-0.0, 0.0) peut produire -0.0.