2010-03-03 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Wed, 3 Mar 2010 18:01:57 +0000 (18:01 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Wed, 3 Mar 2010 18:01:57 +0000 (18:01 -0000)
        * Decimal.cs: Disable the fast double2decimal code, and go back
        * to
        string parsing as there is a rounding/precision bug.

                //
                // We cant use the double2decimal method
                // because it incorrectly turns the floating point
                // value 1.23456789E-25F which should be:
                //    0.0000000000000000000000001235
                // into the incorrect:
                //   0.0000000000000000000000001234
                //
                //    The code currently parses the double value 0.6 as
                //    0.600000000000000
                //
                // And we have a patch for that called (trim

svn path=/trunk/mcs/; revision=152956

mcs/class/corlib/System/Decimal.cs
mcs/class/corlib/Test/System/DecimalTest.cs

index ae85332e687a44cbe1e96185b36439b66b974892..ed7eaa252f7d4da28b71cd230a914159b25f3c54 100644 (file)
@@ -152,14 +152,22 @@ namespace System
 
                public Decimal (float value) 
                {
+#if false
+                       //
+                       // We cant use the double2decimal method
+                       // because it incorrectly turns the floating point
+                       // value 1.23456789E-25F which should be:
+                       //    0.0000000000000000000000001235
+                       // into the incorrect:
+                       //   0.0000000000000000000000001234
+                       //
+                       //    The code currently parses the double value 0.6 as
+                       //    0.600000000000000
+                       //
+                       // And we have a patch for that called (trim
                        if (double2decimal (out this, value, 7) != 0)
                                throw new OverflowException ();
-#if false
-       // This code was introduced in June of 2004 to deal with a
-       // bug at the time with SqlMoney but we have no record
-       // of the bug.   Commented out while we find out why
-       // the unmanaged conversion was taken out and replaced
-       // with the double->string->decimal conversion below
+#else
                        if (value > (float)Decimal.MaxValue || value < (float)Decimal.MinValue ||
                                float.IsNaN (value) || float.IsNegativeInfinity (value) || float.IsPositiveInfinity (value)) {
                                throw new OverflowException (Locale.GetText (
@@ -178,14 +186,22 @@ namespace System
 
                public Decimal (double value) 
                {
+#if false
+                       //
+                       // We cant use the double2decimal method
+                       // because it incorrectly turns the floating point
+                       // value 1.23456789E-25F which should be:
+                       //    0.0000000000000000000000001235
+                       // into the incorrect:
+                       //   0.0000000000000000000000001234
+                       //
+                       //    The code currently parses the double value 0.6 as
+                       //    0.600000000000000
+                       //
+                       // And we have a patch for that called (trim
                        if (double2decimal (out this, value, 15) != 0)
                                throw new OverflowException ();
-#if false
-       // This code was introduced in June of 2004 to deal with a
-       // bug at the time with SqlMoney but we have no record
-       // of the bug.   Commented out while we find out why
-       // the unmanaged conversion was taken out and replaced
-       // with the double->string->decimal conversion below
+#else
                        if (value > (double)Decimal.MaxValue || value < (double)Decimal.MinValue ||
                                double.IsNaN (value) || double.IsNegativeInfinity (value) || double.IsPositiveInfinity (value)) {
                                throw new OverflowException (Locale.GetText (
index 4e5763517126068d5b01d553a358f70943371f77..dd6d8db1edf8826b943451fe346cfcc63102c773 100644 (file)
@@ -677,6 +677,29 @@ namespace MonoTests.System
                        d = new Decimal (1.2342278901234e-25);
                        Assert.AreEqual (d, 1.234e-25m, "A10");
 
+                       //
+                       // Make sure that 0.6 is turned into
+                       // the 96 bit value 6 with the magnitude set to
+                       //
+                       double mydouble = 0.6;
+                       d = new Decimal (mydouble);
+                       int [] bits = Decimal.GetBits (d);
+                       Assert.AreEqual (bits [0], 6, "f1");
+                       Assert.AreEqual (bits [1], 0, "f2");
+                       Assert.AreEqual (bits [2], 0, "f3");
+                       Assert.AreEqual (bits [3], 65536, "f4");
+
+                       //
+                       // Make sure that we properly parse this value
+                       // this in particular exposes a bug in the
+                       // unmanaged version which rounds to 1234 instead
+                       // of 1235, here to make sure we do not regress
+                       // on the future.
+                       //
+                       mydouble = 1.2345679329684657e-25;
+                       d = new Decimal (mydouble);
+                       Assert.AreEqual (d.ToString (), "0.0000000000000000000000001235", "f5");
+                       
                        // test exceptions
                        try {
                                d = new Decimal (8e28);