Come ottenere un risultato di -0 nei calcoli in virgola mobile e distinguerlo da +0 in C #?

StackOverflow https://stackoverflow.com/questions/1043816

  •  20-08-2019
  •  | 
  •  

Domanda

La documentazione MSDN menziona che il tipo double include zero negativo. Tuttavia, entrambi -1.0 / double.PositiveInfinity e -double.Epsilon / 2 sembrano restituire 0 normale (e confrontare uguale ad esso). Come posso ottenere -0?

È stato utile?

Soluzione

Ecco un esempio pratico di differenziazione tra i due senza esaminare i bit. Collegamenti MSDN qui e qui mi ha aiutato a costruire questo esempio.

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);
}

Output:

0
0
-Infinity
Infinity

Prendi nota che -0 e 0 sembrano entrambi uguali per confronti, output, ecc. Ma se dividi 1 per loro, otterrai un -Infinito o Infinito, a seconda dello zero che hai.

Altri suggerimenti

Lo zero negativo ha a che fare con il modo in cui il numero è memorizzato in binario, non alcun risultato reale ottenibile da un calcolo matematico.

Nella memoria a virgola mobile, il bit più in alto viene spesso utilizzato per indicare il segno. Questo lascia 31 bit per i dati (in un valore in virgola mobile a 32 bit), quindi in realtà ci sono due rappresentazioni per zero.

00000000 00000000 00000000 00000000
o
00000000 00000000 00000000 00000001

Entrambi rappresentano zero, ma uno con il bit del segno impostato su negativo.

Naturalmente, questo si verificherebbe normalmente quando si incrementa il numero positivo più alto possibile, ritornerebbe allo zero negativo.

In .net, tuttavia, penso che per impostazione predefinita il tipo esegua i controlli di overflow e genererà un'eccezione anziché consentirti di overflow, quindi l'unico modo per archiviare davvero questo valore è impostarlo direttamente. Inoltre, -0 dovrebbe sempre comparare uguale a +0.

C'è di più al riguardo su Wikipeida

Un modo è usare BitConverter.GetBytes. Se controlli i byte, vedrai che il bit di segno per il valore è effettivamente impostato indicando che è negativo.

byte[] zeroBytes = BitConverter.GetBytes(zero);
byte[] negZeroBytes = BitConverter.GetBytes(negZero);

bool sameBytes = zeroBytes[7] == negZeroBytes[7];

Prova questo. Se pz è zero positivo e nz è zero negativo:

Double.PositiveInfinity/pz => Double.PositiveInfinity
Double.PositiveInfinity/nz => Double.NegativeInfinity

L'ho preso da Specifica ECMA C # .

Puoi ottenere zero negativo dividendo qualsiasi numero positivo per infinito negativo:

10.0/Double.NegativeInfinity

Dopo aver controllato, vedo che -1.0 / double.PositiveInfinity restituisce -0. In effetti, 1.0 / (-1.0 / double.PositiveInfinity) restituisce -infinity .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top