[Mono-bugs] [Bug 34640][Wis] New - Decimal.ToString() fails for some numbers

bugzilla-daemon@rocky.ximian.com bugzilla-daemon@rocky.ximian.com
26 Nov 2002 19:56:15 -0000


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by kend0@earthlink.net.

http://bugzilla.ximian.com/show_bug.cgi?id=34640

--- shadow/34640	Tue Nov 26 14:56:15 2002
+++ shadow/34640.tmp.3840	Tue Nov 26 14:56:15 2002
@@ -0,0 +1,283 @@
+Bug#: 34640
+Product: Mono/Class Libraries
+Version: unspecified
+OS: Red Hat 7.2
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Wishlist
+Component: System
+AssignedTo: mono-bugs@ximian.com                            
+ReportedBy: kend0@earthlink.net               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Decimal.ToString() fails for some numbers
+
+version: Mono/mcs  0.13
+
+Description of Problem:
+
+  ToString() fails for some Decimal numbers.  (see Actual, below).
+
+  The salient traceback is: VVVVV
+Unhandled Exception: System.ArgumentException: length
+in <0x00210> 00 System.Array:Copy (System.Array,int,System.Array,int,int)
+in <0x000a5> 00 System.Text.StringBuilder:Remove (int,int)
+in <0x000be> 00 System.DecimalFormatter:FormatGeneral (System.Globalization.NumberFormatInfo,System.Text.StringBuilder,int,int,int,char)
+in <0x003e9> 00 System.DecimalFormatter:NumberToString (string,System.Globalization.NumberFormatInfo,System.Decimal)
+in <0x0005c> 00 System.Decimal:ToString (string,System.IFormatProvider)
+in <0x00475> 00 LFT.RunMe:Main (string[])
+                                                    ^^^^^
+
+
+Steps to reproduce the problem:
+1. compile and run the following program
+VVVVVVVVVVVVVVVVVVVVVVVVVV
+// FILE       "lft.cs"
+// IMPLEMENTS Linear Fractional Transform (Mobius Transform) real numbers
+// AUTHOR     Ken Dickey
+// DATE       2002 November 26
+// Copyright (C) 2002 by Kenneth Alan Dickey. All rights reserved.
+
+using System ;
+using System.IO ;
+using System.Math ;
+using System.Collections ;
+
+namespace LFT {
+    public class LFTMat {
+	Int64 a = 0, b = 0, c = 0, d = 1 ;
+	//  | a c |
+	//  | b d |
+	public LFTMat( Int64 a, Int64 b, Int64 c, Int64 d ) {
+	    this.a = a ;
+	    this.b = b ;
+	    this.c = c ;
+	    this.d = d ;
+	    // return( this ) ;
+	}
+	public override String ToString() {
+	    return "<LFT: a=" + this.a.ToString()
+		+ ", b=" + this.b.ToString()
+		+ ", c=" + this.c.ToString()
+		+ ", d=" + this.d.ToString()
+		+ ">";
+	}
+	public Decimal mash( Decimal x ) {
+	    //  | a c |
+	    //  | b d | => ( ax+c / bx+d )
+	    return ( (this.a * x + this.c) / (this.b * x + this.d) ) ;
+	}
+	public Boolean isAffine() {
+	    return ( (this.b == 0) && (this.d != 0) ) ;
+	}
+	public Int64 determinant() {
+	    // (ad - bc)
+	    return ((this.a * this.d) - (this.b * this.c)) ;
+	}
+	public Boolean isSingular() {
+	    return (this.determinant() != 0) ;
+	}
+	public LFTMat inverse() {
+	    if (this.isSingular())
+		throw new Exception("LFTMat.inverse: is singular" + this.ToString()) ;
+	    else
+		return( new LFTMat( d, -b, -c, a ) ) ;
+	}
+	public static LFTMat operator+(  LFTMat x,  LFTMat y ) {
+	    return( new
+		LFTMat( x.a + y.a ,
+			x.b + y.b ,
+			x.c + y.c ,
+			x.d + y.d ) ) ;
+	}
+	public static LFTMat operator-(  LFTMat x,  LFTMat y ) {
+	    return( new
+		LFTMat( x.a - y.a ,
+			x.b - y.b ,
+			x.c - y.c ,
+			x.d - y.d ) ) ;
+	}
+	public static LFTMat operator*(  LFTMat x,  LFTMat y ) {
+	    // product:
+	    // | a1 c1 |   | a2 c2 |   | (a1a2 + c1b2) (a1c2 + c1d2) |
+	    // | b1 d1 | * | b2 d2 | = | (b1a2 + d1b2) (b1c2 + d1d2) |
+	    return( new
+		LFTMat( x.a * y.a + x.c * y.b ,
+			x.b * y.a + x.d * y.b ,
+			x.a * y.c + x.c * y.d ,
+			x.b * y.c + x.d * y.d ) ) ;
+	}
+	public Boolean isRefining() {
+	    return( this.isAffine() && 
+		    ( (Math.Abs(this.a) + Math.Abs(this.c)) <= Math.Abs(this.d) )
+		  ) ;
+	}
+	public Decimal contractivity() {
+	    if (this.isAffine())
+		return( Math.Abs(this.a / this.b) ) ;
+	    else
+		throw new Exception("LFTMat.contractivity: is NOT affine" 
+				    + this.ToString()) ;
+	}
+    } // end LFTMat
+    
+    public class LFT {
+	public static Boolean debugMe = true ;
+	LFTMat   sign;
+	LFTMat[] digits;
+	public LFT( LFTMat sign, LFTMat[] digits ) {
+	    this.sign   = sign ;
+	    this.digits = digits ;
+	    // return( this ) ;
+	}
+    } // end LFT
+    public class E_LFT {
+	Int64 x ;
+	public E_LFT( Int64 x ) {
+	    this.x = x ;
+	    // return( this ) ;
+	}
+	// e^x = | x x+1 |  ------oo   | x  x  |
+	//       | 0  1  |   |  |n=1   | 0 n+1 |
+	public Decimal mash( Int64 whatever ) { 
+	    // mash( sign * digit1 * ... * digitN )
+	    Int64 x = this.x ;
+	    LFTMat sign = new LFTMat( x, 0, (x+1), 1 ) ;
+	    LFTMat tmp = sign ;
+	    for (int n = 1; n <= whatever; n++)
+		tmp = tmp * (new LFTMat( x, 0, x, (n + 1) )) ;
+	    if (LFT.debugMe) {
+		Console.WriteLine( "E-LFT for n={0} is {1}", whatever, tmp ) ;
+		Decimal result = tmp.mash( x ) ;
+		//Console.WriteLine( "E-LFT result is {0}", (Double)result ) ;
+		return( result ) ;
+	    }
+	    else
+		return( tmp.mash( x ) ) ;
+	}
+	    
+    } // end E_LFT
+
+    public class RunMe {
+	static void Main(string[] args)
+	{
+	    LFTMat a = new LFTMat( 1, 0, 2, 1 ) ;
+	    LFTMat b = new LFTMat( 1, 1, 0, 2 ) ;
+	    Console.WriteLine("**VVV Starting Linear Transform Code VVV**") ;
+	    Console.WriteLine("A is {0}", a.ToString() ) ;
+	    Console.WriteLine("B is {0}", b.ToString() ) ;
+	    Console.WriteLine("A + B is {0}", (a+b).ToString() ) ;
+	    Console.WriteLine("A - B is {0}", (a-b).ToString() ) ;
+	    Console.WriteLine("A * B is {0}", (a*b).ToString() ) ;
+	    Console.WriteLine("A.mash(3) is {0}", a.mash(3).ToString() ) ;
+	    E_LFT e = new E_LFT( 1 ) ; // e^1 is e
+	    Console.WriteLine("Math.E is {0}", Math.E.ToString() ) ;
+	    Decimal approx = 3 ;
+	    Decimal bigE   = (Decimal)Math.E ;
+	    Decimal delta  = (Decimal)0.00000000000001 ;
+	    Int64   n = 1 ;
+	    while ( (Math.Abs(approx - bigE) > delta) ) {
+		approx =  e.mash(n) ;
+		Console.WriteLine( "eLFT.mash({0}) is {1}", 
+				   n.ToString(), 
+				   approx.ToString() //((Double)approx).ToString()
+				 ) ;
+		n = (n + 1) ;
+	    }
+	    Console.WriteLine("Math.E        is {0}", Math.E.ToString() ) ;
+	    Console.WriteLine("**^^^  Ending Linear Transform Code  ^^^**") ;
+	}
+    } // end RunMe
+}
+
+
+/*			--- E O F ---			*/
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Actual Results:
+
+kend@bandicoot:/usr/local/src/Mono/Test>> mcs lft.cs
+lft.cs(123) warning CS0162: Unreachable code detected
+Compilation succeeded - 1 warning(s)
+kend@bandicoot:/usr/local/src/Mono/Test>> mono lft.exe
+**VVV Starting Linear Transform Code VVV**
+A is <LFT: a=1, b=0, c=2, d=1>
+B is <LFT: a=1, b=1, c=0, d=2>
+A + B is <LFT: a=2, b=1, c=2, d=3>
+A - B is <LFT: a=0, b=-1, c=2, d=-1>
+A * B is <LFT: a=3, b=1, c=4, d=2>
+A.mash(3) is 5
+Math.E is 2.71828182845905
+E-LFT for n=1 is <LFT: a=1, b=0, c=5, d=2>
+eLFT.mash(1) is 3
+E-LFT for n=2 is <LFT: a=1, b=0, c=16, d=6>
+eLFT.mash(2) is 2.8333333333333333333333333333
+E-LFT for n=3 is <LFT: a=1, b=0, c=65, d=24>
+eLFT.mash(3) is 2.75
+E-LFT for n=4 is <LFT: a=1, b=0, c=326, d=120>
+
+Unhandled Exception: System.ArgumentException: length
+in <0x00210> 00 System.Array:Copy (System.Array,int,System.Array,int,int)
+in <0x000a5> 00 System.Text.StringBuilder:Remove (int,int)
+in <0x000be> 00 System.DecimalFormatter:FormatGeneral (System.Globalization.NumberFormatInfo,System.Text.StringBuilder,int,int,int,char)
+in <0x003e9> 00 System.DecimalFormatter:NumberToString (string,System.Globalization.NumberFormatInfo,System.Decimal)
+in <0x0005c> 00 System.Decimal:ToString (string,System.IFormatProvider)
+in <0x00475> 00 LFT.RunMe:Main (string[])
+
+kend@bandicoot:/usr/local/src/Mono/Test>> 
+
+Expected Results:
+
+[obtained by casting result to Double before output]
+**VVV Starting Linear Transform Code VVV**
+A is <LFT: a=1, b=0, c=2, d=1>
+B is <LFT: a=1, b=1, c=0, d=2>
+A + B is <LFT: a=2, b=1, c=2, d=3>
+A - B is <LFT: a=0, b=-1, c=2, d=-1>
+A * B is <LFT: a=3, b=1, c=4, d=2>
+A.mash(3) is 5
+Math.E is 2.71828182845905
+E-LFT for n=1 is <LFT: a=1, b=0, c=5, d=2>
+eLFT.mash(1) is 3
+E-LFT for n=2 is <LFT: a=1, b=0, c=16, d=6>
+eLFT.mash(2) is 2.83333333333333
+E-LFT for n=3 is <LFT: a=1, b=0, c=65, d=24>
+eLFT.mash(3) is 2.75
+E-LFT for n=4 is <LFT: a=1, b=0, c=326, d=120>
+eLFT.mash(4) is 2.725
+E-LFT for n=5 is <LFT: a=1, b=0, c=1957, d=720>
+eLFT.mash(5) is 2.71944444444444
+E-LFT for n=6 is <LFT: a=1, b=0, c=13700, d=5040>
+eLFT.mash(6) is 2.71845238095238
+E-LFT for n=7 is <LFT: a=1, b=0, c=109601, d=40320>
+eLFT.mash(7) is 2.71830357142857
+E-LFT for n=8 is <LFT: a=1, b=0, c=986410, d=362880>
+eLFT.mash(8) is 2.71828428130511
+E-LFT for n=9 is <LFT: a=1, b=0, c=9864101, d=3628800>
+eLFT.mash(9) is 2.71828207671958
+E-LFT for n=10 is <LFT: a=1, b=0, c=108505112, d=39916800>
+eLFT.mash(10) is 2.7182818512506
+E-LFT for n=11 is <LFT: a=1, b=0, c=1302061345, d=479001600>
+eLFT.mash(11) is 2.71828183037384
+E-LFT for n=12 is <LFT: a=1, b=0, c=16926797486, d=6227020800>
+eLFT.mash(12) is 2.71828182860735
+E-LFT for n=13 is <LFT: a=1, b=0, c=236975164805, d=87178291200>
+eLFT.mash(13) is 2.7182818284697
+E-LFT for n=14 is <LFT: a=1, b=0, c=3554627472076, d=1307674368000>
+eLFT.mash(14) is 2.71828182845976
+E-LFT for n=15 is <LFT: a=1, b=0, c=56874039553217, d=20922789888000>
+eLFT.mash(15) is 2.71828182845909
+E-LFT for n=16 is <LFT: a=1, b=0, c=966858672404690, d=355687428096000>
+eLFT.mash(16) is 2.71828182845905
+Math.E        is 2.71828182845905
+**^^^  Ending Linear Transform Code  ^^^**
+
+
+How often does this happen? 
+
+
+Additional Information: