Udostępnij za pośrednictwem


Decimal Negative Zero Representation [Lakshan Fernando]

One of our customers wondered recently if we represent negative zero in Decimal. At first glance, it doesn’t look to be the case as seen below;

   Decimal zero = Decimal.Zero;   Decimal negativeZero_1 = new Decimal(0, 0, 0, true, 0);   Decimal negativeZero_2 = -0.0m;    Decimal negativeZero_3 = Decimal.Negate(Decimal.Zero);   Console.WriteLine("Negative Zero: {0}, {1}, {2} Positive Zero: {3}", negativeZero_1, negativeZero_2, negativeZero_3, zero);   Console.WriteLine("Negative and Positive Zero comparison: {0}", zero.CompareTo(negativeZero_1));

Will output

Negative Zero: 0, 0, 0 Positive Zero: 0
Negative and Positive Zero comparison: 0

But we do recognize negative zero and persist the information in the bit representation and can be seen via the Decimal.GetBits method. Calling the following method for the above 4 Decimal values,

   public staticString HexValue(Decimal value)    {       Int32[] bits = Decimal.GetBits(value);       return String.Format("{{0x{0:X8} {1:X8} {2:X8} {3:X8} }}", bits[0], bits[1], bits[2], bits[3]);    }

Will output,

zero: {0x00000000 00000000 00000000 00000000 }
negativeZero_1: {0x00000000 00000000 00000000 80000000 }
negativeZero_2: {0x00000000 00000000 00000000 80010000 }
negativeZero_3: {0x00000000 00000000 00000000 80000000 }

We don’t show a negative decimal in the ToString() method because it was considered more clean to do it this way.  Some applications depend on zero printing as “0” whether it is “positive” or “negative” zero.  Likewise, the two decimals compare Equal, because they represent the same value, regardless of scale or sign (see also https://www.w3.org/TR/2006/WD-xmlschema11-2-20060217/#precisionDecimal).  Our documentation for Decimal.GetBits mentions the bit representation for Negative zero. BTW, C# compiler does not treat “-0m” as negative zero, although it does get both the sign and the scale correctly for “-0.0m”

It would be interesting to know of any applications build on top of this.

Comments

  • Anonymous
    October 20, 2006
    Keep up the good work.  This blog to me is one of the most important.  And BTW, please continue to evolve and improve the Decimal class.  An example, impliment a Decminal sepecific Pow method.  Decimal::Pow().  The Math::Pow() uses doubles.  Precision is lost, or at least I can't control it.

  • Anonymous
    February 19, 2008
    Somewhere in between zero and the smallest possible negative number there lies another number. NEGATIVE

  • Anonymous
    April 28, 2008
    The weirdness is easily noted if you try the following code in both .NET <= 1.1 and .NET >= 2.0: