Comment obtenir un résultat -0 dans les calculs en virgule flottante et le distinguer de +0 en C #?
-
20-08-2019 - |
Question
La documentation MSDN mentionne que le type double
comprend un zéro négatif. Cependant, -1.0 / double.PositiveInfinity
et -double.Epsilon / 2
semblent renvoyer un nombre normal de 0 (et se comparer à ce niveau). Comment puis-je obtenir -0?
La solution
Voici un exemple pratique de différenciation entre les deux sans examiner les bits. Liens MSDN ici et ici m'a aidé à construire cet exemple.
static void Main(string[] args)
{
float a = 5 / float.NegativeInfinity;
float b = 5 / float.PositiveInfinity;
float c = 1 / a;
float d = 1 / b;
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
}
Sortie:
0
0
-Infinity
Infinity
Notez que -0 et 0 se ressemblent pour les comparaisons, les sorties, etc. Mais si vous divisez 1 par eux, vous obtenez -Infinity ou Infinity, selon le zéro que vous avez.
Autres conseils
Le zéro négatif a à voir avec la façon dont le nombre est stocké en binaire, pas avec un résultat réel pouvant être obtenu à partir d'un calcul mathématique.
Dans la mémoire en virgule flottante, le bit le plus haut est souvent utilisé pour indiquer le signe. Cela laisse 31 bits pour les données (dans une valeur à virgule flottante de 32 bits), il y a donc deux représentations pour zéro.
00000000 00000000 00000000 00000000
Ou
00000000 00000000 00000000 00000001
Les deux représentent zéro, mais un avec le bit de signe défini sur négatif.
Naturellement, cela se produirait normalement lorsque vous incrémenteriez le nombre positif le plus élevé possible, il déborderait à zéro.
Cependant, je pense que, par défaut, le type vérifie le dépassement de capacité et génère une exception au lieu de vous laisser déborder. Le seul moyen d'archiver réellement cette valeur consiste à le définir directement. En outre, -0 devrait toujours être égal à +0.
Vous en saurez plus sur Wikipeida
L’une des méthodes consiste à utiliser BitConverter.GetBytes. Si vous vérifiez les octets, vous verrez que le bit de signe de la valeur est effectivement défini, ce qui indique que son négatif est.
byte[] zeroBytes = BitConverter.GetBytes(zero);
byte[] negZeroBytes = BitConverter.GetBytes(negZero);
bool sameBytes = zeroBytes[7] == negZeroBytes[7];
Essayez ceci. Si pz
est positif (zéro) et que nz
est négatif (zéro):
Double.PositiveInfinity/pz => Double.PositiveInfinity
Double.PositiveInfinity/nz => Double.NegativeInfinity
Cela provient de la spécification ECMA C # .
Vous pouvez obtenir un zéro négatif en divisant tout nombre positif par un infini négatif:
10.0/Double.NegativeInfinity
Après vérification, je constate que -1.0 / double.PositiveInfinity
renvoie le résultat -0. En effet, 1.0 / (-1.0 / double.PositiveInfinity)
renvoie -infinity
.