Skip to main content
GameDev.net gamedev.net
🔒 Locked

[.net] Bignum datatpe in .net

Started by nolongerhere Feb 17, 2006 at 6:17 PM 11 replies 5.4k views
Original Post
nolongerhere
nolongerhere
Are there any implementations of the bignum datatype in .net/C#? Does anyone have any good sources for creating it? (if you dont know what bignums are... http://en.wikipedia.org/wiki/Bignum )
Bob Janova
Bob Janova
I wrote one as an intellectual exercise for myself. I rather doubt it's efficient, but I can send you it if you like.
nolongerhere
nolongerhere
Thanks for the fast reply and yes, please do email it to me. (azh321@gmail.com)
joanusdmentia
joanusdmentia
Check out the System.Decimal type. It's still limited in size like the builtin types but the limit is ridiculously large, about 3 billion times larger than a 64-bit integer.
"Voilà! In view, a humble vaudevillian veteran, cast vicariously as both victim and villain by the vicissitudes of Fate. This visage, no mere veneer of vanity, is a vestige of the vox populi, now vacant, vanished. However, this valorous visitation of a bygone vexation stands vivified, and has vowed to vanquish these venal and virulent vermin vanguarding vice and vouchsafing the violently vicious and voracious violation of volition. The nly verdict is vengeance; a vendett o
Conner McCloud
Conner McCloud
Quote:
Original post by joanusdmentia
Check out the System.Decimal type. It's still limited in size like the builtin types but the limit is ridiculously large, about 3 billion times larger than a 64-bit integer.

Quote:

The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors.

Wow. If infinity were a number, I'll bet it would fit in a System.Decimal object.

CM
turnpast
turnpast
here is something I found over at codeproject.
Bob Janova
Bob Janova
OK, well here's mine (it's a single C# file so you can paste it from here – better than emailing imho as other people can see it too).

// LargeInteger.cs// Extensible integer classusing System;using System.Text;[assembly:System.Reflection.AssemblyVersion("1.0.2005.0906")]namespace RedCorona.Utils {	public struct LargeInteger {		internal UInt32[] data;		public bool negative;		public int Shift, Exponent;		public static Random RandomGenerator = new Random();				// Used for displaying the numbers ... only calculate once		internal static LargeInteger[] PowersOfGiga = new LargeInteger[0];		internal static int[] MiniPowers = new int[]{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};				public LargeInteger(UInt32 num){ data = new uint[1]; data[0] = num; negative = false; Shift = 0; Exponent = 0;}		public LargeInteger(int num){			negative = num < 0;			if(negative) num = -num;			data = new uint[1]; data[0] = (uint)num;			Shift = 0; Exponent = 0;		}		public LargeInteger(UInt64 num){ data = new uint[2]; data[0] = (uint)num; data[1] = (uint)(num >> 32); negative = false; Shift = 0; Exponent = 0;}		public LargeInteger(Int64 num){			negative = num < 0;			if(negative) num = -num;			data = new uint[2]; data[0] = (uint)num; data[1] = (uint)(num >> 32);			Shift = 0; Exponent = 0;		}		public LargeInteger(int num, int exp) : this(num, exp, 0) {}		public LargeInteger(int num, int exp, int shift){			this = new LargeInteger(num);			this.Exponent = exp;			this.Shift = shift;		}		public LargeInteger(double d){			this = Parse(d.ToString(System.Globalization.CultureInfo.InvariantCulture));			/*			// Shift the denominator left until we get a hit, and then keep coming back			// Assume they're trimmed and use the size difference as a first guess			int exp = 0, limit;			bool neg = d < 0, first = true;			double d2 = d, d3;			if(neg) d = -d;			Shift = 0; Exponent = 0;						while(new LargeInteger(1,exp).DoubleValue < d) exp++;			exp--;			negative = false;			d2 = 0;			limit = exp - 16;			data = new uint[0];			// Shift is now high enough that we can just move down and clock the			// result whenever we get one			for(; (d != d2) && (exp > limit); exp--){				LargeInteger currentDivisor = new LargeInteger(1,exp);				double dd = currentDivisor.DoubleValue;				d3 = ((2 * d) - d2); // d + D				Console.WriteLine("d': "+(d+dd)+"; dd: "+dd+"; d3: "+d3+"; f: "+(int)((d / dd) % 1000));				if(d3 >= dd + d){					int fac = ((int)((d / dd) % 1000)) % 10;					//if(fac > 10) fac -= 10;					//if(first) fac--;					this += (fac * currentDivisor);					//d -= (dd * fac);					d2 += (fac * dd);					//Console.WriteLine("Adding "+ (fac * currentDivisor) + "; d is "+d+"; d2 is now "+d2+"; dd is "+dd);				}				first = false;			}			negative = neg;			Trim();*/		}				public static LargeInteger Parse(String s){			// Allow int definiton (34, -2256), large int (1234567890987654321)			// or double definition (12.6, 1e300, etc)			LargeInteger res = new LargeInteger(0);						if(s[0] == '`'){				// Special format to ensure exact reproduction				s = s.Substring(1);				int p = s.IndexOf('`');				int size = Int32.Parse(s.Substring(0, p));				s = s.Substring(p + 1);								p = s.IndexOf('`');				res.Shift = Int32.Parse(s.Substring(0, p));				s = s.Substring(p + 1);								p = s.IndexOf('`');				res.Exponent = Int32.Parse(s.Substring(0, p));				s = s.Substring(p + 1);								p = s.IndexOf('`');				res.negative = (s.Substring(0, p) != "0");				s = s.Substring(p + 1);								res.data = new uint[size];				for(int i = 0; i < size; i++){					res.data = UInt32.Parse(s.Substring(0, 8), System.Globalization.NumberStyles.HexNumber);					s = s.Substring(8);				}								return res;			}						int exppos = s.IndexOf('e');			if(exppos < 0) exppos = s.IndexOf('E');			String num; int exp;			if(exppos > 0){				try { 					exp = Int32.Parse(s.Substring(exppos + 1));				} catch {					throw new FormatException("Invalid exponent: "+s.Substring(exppos + 1));				}				num = s.Substring(0, exppos);			} else {				exp = 0;				num = s;			}						int dppos = num.IndexOf('.');			if(dppos >= 0){				exp -= s.Length - dppos - 1;				num = num.Substring(0, dppos) + num.Substring(dppos + 1);				Console.WriteLine("After removing dp, num is "+num);			}						try{				res = new LargeInteger(Int32.Parse(num));				res.Exponent = exp;				return res;			} catch(OverflowException) {				// It overflowed, so we'd better do it by hand				int len = num.Length;				if(num[0] == '-'){					num = num.Substring(1);					res.negative = true;				}				EnsureGigasFilled((len / 9) + 1);				int i = 0;				while(num.Length >= 9){					LargeInteger next = UInt32.Parse(num.Substring(num.Length - 9));					res += next * PowersOfGiga[i++];					num = num.Substring(0, num.Length - 9);				}								if(s.Length > 0){					LargeInteger next = UInt32.Parse(num);					res += next * PowersOfGiga[i++];				}								res.Exponent = exp;				return res;			} //catch(Exception){ 				//try {					//res = new LargeInteger(Double.Parse(num));				//	res.Exponent += Int32.Parse(exp);				//	return res;				//} catch(Exception){ 				//	throw new FormatException("Could not parse string "+num);				//}			//}		}				public static LargeInteger Random(LargeInteger li){			LargeInteger res = li.Clone();			res.Trim(); res.Expand(res.Shift); res.ExpandExponent(res.Exponent);						// For each block other than the highest, it is Random($FFFFFFFF)			for(int i = 0; i < res.Size - 1; i++){				res.data = (uint)RandomGenerator.Next(0x10000000);				res.data += (uint)RandomGenerator.Next(0x10) << 28;			}						// Highest block is Random(value)			uint val = res.data[res.Size - 1];			if(val > 0x7FFFFFFF){				res.data[res.Size - 1] = (uint)RandomGenerator.Next(0x10000000);				res.data[res.Size - 1] += (uint)RandomGenerator.Next((int)(val >> 28)) << 28;			} else res.data[res.Size - 1] = (uint)RandomGenerator.Next((int)val);						return res;		}				// Valid typecasts		public static implicit operator LargeInteger(long num){ return new LargeInteger(num); }		public static implicit operator LargeInteger(ulong num){ return new LargeInteger(num); }		public static implicit operator LargeInteger(int num){ return new LargeInteger(num); }		public static implicit operator LargeInteger(uint num){ return new LargeInteger(num); }		public static implicit operator LargeInteger(float num){ return new LargeInteger(num); }		public static implicit operator LargeInteger(double num){ return new LargeInteger(num); }				// Operations		public static LargeInteger operator +(LargeInteger i1, LargeInteger i2){			LargeInteger res;			bool sub = false;			// Need to move shifts so the result is perfectly accurate			int s1 = i1.Shift, s2 = i2.Shift;			i1.Shift = 0; i2.Shift = 0;			if(s2 < s1){				i1 = i1.ShiftLeft(s1 - s2);				res.Shift = s2;			} else if(s2 > s1) {				i2 = i2.ShiftLeft(s2 - s1);				res.Shift = s1;			} else res.Shift = s1;			int e1 = i1.Exponent, e2 = i2.Exponent;			i1.Exponent = 0; i2.Exponent = 0;			if(e2 < e1){				i1 *= PowerOf10(e1 - e2);				res.Exponent = e2;			} else if(e2 > e1) {				i2 *= PowerOf10(e2 - e1);				res.Exponent = e1;			} else res.Exponent = e1;			//			Console.WriteLine("res sh = "+res.Shift);			res.negative = i1.negative;			if(i1.negative != i2.negative){				// One negative, one positive, make sure we get a positive result by switching				// signs, always make i1 bigger				if(i2 > i1){					LargeInteger temp = i2; i2 = i1; i1 = temp;					res.negative = !res.negative;				}				sub = true;			}			int size = i1.Size;			if(i2.Size > size) size = i2.Size;			res.data = new uint[size + 1];			res.data[size] = 0;			long carry = 0, v1, v2;//Console.WriteLine("Add set up. size "+size);						for(int i = 0; i < size; i++){				if(i >= i1.Size) v1 = 0; else v1 = i1.data;				if(i >= i2.Size) v2 = 0; else v2 = i2.data;								if(sub) v2 = -v2;				long val = v1 + v2 + carry;				res.data = unchecked((uint)val);				carry = val >> 32;//Console.WriteLine("In Sum inner loop, v1 = "+v1+", v2 = "+v2+", val is "+val+", carrying "+carry);				res.data[i + 1] = (uint)carry;			}			//Console.WriteLine("End.");			return res.Trim();		}				public static LargeInteger operator ~(LargeInteger i1){			LargeInteger li = i1.Clone();			for(int i = 0; i < li.Size; i++) li.data = ~li.data;			return li;		}				public static LargeInteger operator -(LargeInteger i1){			LargeInteger li = i1.Clone();			li.negative = !li.negative;			return li;		}		public static LargeInteger operator -(LargeInteger i1, LargeInteger i2){	return i1 + (-i2); }				public static LargeInteger operator *(LargeInteger i1, LargeInteger i2){			LargeInteger res = new LargeInteger();			res.negative = false; res.Shift = 0; res.Exponent = 0;			int sh = i1.Shift + i2.Shift;			int exp = i1.Exponent + i2.Exponent;			i1.Shift = 0; i2.Shift = 0; i1.Exponent = 0; i2.Exponent = 0;			int size = i1.Size + i2.Size;			res.data = new uint[size];			// Take blocks in units of 2 bytes to avoid overflow			for(int i = 0; i < i1.Size; i++){				uint lo1 = i1.data & 0xFFFF, hi1 = (i1.data & 0xFFFF0000) >> 16;				for(int j = 0; j < i2.Size; j++){					uint lo2 = i2.data[j] & 0xFFFF, hi2 = (i2.data[j] & 0xFFFF0000) >> 16;					int loloshift = (i * 32) + (j * 32);//Console.WriteLine("In Mul inner sum, v1="+hi1.ToString("X")+":"+lo1.ToString("X")+", v2="+hi2.ToString("X")+":"+lo2.ToString("X")+", shift="+loloshift);					res += new LargeInteger(lo1 * lo2).ShiftLeft(loloshift);					res += (new LargeInteger(hi1 * lo2) + new LargeInteger(lo1 * hi2)).ShiftLeft((loloshift + 16));					res += new LargeInteger(hi1 * hi2).ShiftLeft((loloshift + 32));					res.Trim();				}			}			res.negative = i1.negative != i2.negative;			res.Shift = sh; res.Exponent = exp;			return res.Trim();		}				public static LargeInteger operator /(LargeInteger i1, LargeInteger i2){			return DoDivOrMod(i1, i2, 1);		}				public static LargeInteger operator %(LargeInteger i1, LargeInteger i2){			i1.Expand(i1.Shift).ExpandExponent(i1.Exponent);			i2.Expand(i2.Shift).ExpandExponent(i2.Exponent);			LargeInteger lastmod = DoDivOrMod(i1, i2, i2);			return i1 - lastmod;		}				public static LargeInteger operator <<(LargeInteger i1, int shift){			i1.Shift += shift;			return i1;		}				public static LargeInteger operator >>(LargeInteger i1, int shift){			i1.Shift -= shift;			return i1;		}				public static LargeInteger operator &(LargeInteger i1, LargeInteger i2){			int size = i1.Size;			if(i2.Size > size) size = i2.Size;			LargeInteger res;			res.data = new uint[size];			res.negative = i1.negative & i2.negative;			res.Shift = 0; res.Exponent = 0;			uint v1, v2;			for(int i = size - 1; i >= 0; i--){				if(i >= i1.Size) v1 = 0; else v1 = i1.data;				if(i >= i2.Size) v2 = 0; else v2 = i2.data;								res.data = v1 & v2;			}			return res;		}				public static LargeInteger operator |(LargeInteger i1, LargeInteger i2){			int size = i1.Size;			if(i2.Size > size) size = i2.Size;			LargeInteger res;			res.Shift = 0; res.Exponent = 0;			res.data = new uint[size];			res.negative = i1.negative | i2.negative;			uint v1, v2;			for(int i = size - 1; i >= 0; i--){				if(i >= i1.Size) v1 = 0; else v1 = i1.data;				if(i >= i2.Size) v2 = 0; else v2 = i2.data;								res.data = v1 | v2;			}			return res;		}				public static bool operator >(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, false, true, false); }		public static bool operator >=(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, false, true, true); }		public static bool operator <=(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, true, false, true); }		public static bool operator <(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, true, false, false); }		public static bool operator ==(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, false, false, true); }		public static bool operator !=(LargeInteger i1, LargeInteger i2){ return DoLogicalOp(i1, i2, true, true, false); }				// Functions and properties		public int Size { get { return data.Length; } }				public LargeInteger ShiftLeft(int by){			if(by < 0) return ShiftRight(-by);			LargeInteger li = this;			if(by == 0) return this;			uint[] data;			int wholeblocks = by / 32;			int size = li.Size + wholeblocks + 1;			data = new uint[size];			for(int i = 0; i < size; i++) data = 0;			by %= 32;									for(int i = li.Size - 1; i >= 0; i--){				data[i + wholeblocks] = li.data << by;				if(by > 0) data[i + wholeblocks + 1] += li.data >> (32 - by);			}						li.data = data;			return li.Trim();		}				public LargeInteger ShiftRight(int by){			if(by < 0) return ShiftLeft(-by);			LargeInteger li = this.Clone();			if(by == 0) return li;			uint[] data;			int wholeblocks = by / 32;			int size = li.Size - wholeblocks;			if(size <= 0) return 0;			//Console.WriteLine("SHR by "+by+"; New size "+size+", old size "+li.Size);						data = new uint[size];//			for(int i = 0; i < size; i++)//				data = li.data[i + wholeblocks];			by %= 32;						for(int i = 0; i < size; i++){				data = li.data[i + wholeblocks] >> by;				if((i > 0) && (by > 0)){					//Console.WriteLine("SHR of "+data[i - 1].ToString("X")+" onto "+(li.data[i + wholeblocks] << (32 - by)).ToString("X"));					data[i - 1] += li.data[i + wholeblocks] << (32 - by);				}			}						li.data = data;			return li.Trim();		}				internal static LargeInteger DoDivOrMod(LargeInteger i1, LargeInteger i2, LargeInteger adder){			if(i2 == 0) throw new DivideByZeroException("Divide by zero");			LargeInteger res = new LargeInteger();			int sh = i1.Shift - i2.Shift;			i1.Shift = 0; i2.Shift = 0; res.Shift = 0;			int exp = i1.Exponent - i2.Exponent;			i1.Exponent = 0; i2.Exponent = 0; res.Exponent = 0;			bool negative = i1.negative != i2.negative;			i1.negative = i2.negative = false;			res.data = new uint[i1.Size];						// Shift the denominator left until we get a hit, and then keep coming back			// Assume they're trimmed and use the size difference as a first guess			int shift = (i1.Size - i2.Size) * 32;			if(shift < 0) shift = 0; // the second is larger ... we'll probably get 0						while(i2.ShiftLeft(shift) < i1) shift++;						// Shift is now high enough that we can just move down and clock the			// result whenever we get one			for(; shift >= 0; shift--){				LargeInteger currentDivisor = i2.ShiftLeft(shift);				if(i1 >= currentDivisor){					res += adder.ShiftLeft(shift);					i1 -= currentDivisor;				}			}			res.negative = negative;			res.Shift = sh; res.Exponent = exp;			return res.Trim();		}				public LargeInteger Power(int power){			if(power >= 0) return Power((uint)power);			else return 1 / Power((uint)-power);		}				public LargeInteger Power(uint power){			// Algorithm after Sullivan, Vector 12.1			LargeInteger result = 1;			Compress();			//for(int i = 0; i < power; i++) result *= this;			bool started = false;						for(int i = 31; i >= 0; i--){				if(started) result *= result;				//Console.WriteLine("i = "+i+"; r = "+result);				if(((power >> i) % 2) == 1){					started = true;					result *= this;					result.Compress();				}			}						if((power % 2) == 0) result.negative = false;			else result.negative = negative;			return result;		}				internal static bool DoLogicalOp(LargeInteger i1, LargeInteger i2, bool Lessthan, bool Greaterthan, bool Equal){			// Clear out the exponent and shift			//Console.Write("Logical op "+i1+" "+i2);			if(i1.Shift > i2.Shift) i1.Expand(i1.Shift - i2.Shift);			else if(i1.Shift < i2.Shift) i2.Expand(i2.Shift - i1.Shift);						if(i1.Exponent > i2.Exponent) i1.ExpandExponent(i1.Exponent - i2.Exponent);			else if(i1.Exponent < i2.Exponent) i2.ExpandExponent(i2.Exponent - i1.Exponent);						//Console.WriteLine("... => "+i1+" "+i2);						int size = i1.Size;			if(i2.Size > size) size = i2.Size;			uint v1, v2;			for(int i = size - 1; i >= 0; i--){				if(i >= i1.Size) v1 = 0; else v1 = i1.data;				if(i >= i2.Size) v2 = 0; else v2 = i2.data;								if(v1 > v2) return Greaterthan;				else if(v1 < v2) return Lessthan;			}			return Equal;		}				public override bool Equals(object obj){			if(!(obj is LargeInteger)) return false;			return this == (LargeInteger)obj;		}				public override int GetHashCode(){			uint res = 0;			for(int i = 0; i < Size; i++) res ^= data;			return (int)res;		}				public override String ToString(){			return DoubleValue.ToString();		}				public String ToHexString(){			String res = "";			for(int i = 0; i < Size; i++)				res = data.ToString("X8") + res;			res = "0x" + res;			if(negative) res = "-"+res;			if(Shift != 0) res += ", sh "+Shift;			if(Exponent != 0) res += ", exp "+Exponent;			return res;		}				internal static void EnsureGigasFilled(int upto){			if(upto <= PowersOfGiga.Length) return;			LargeInteger[] old = PowersOfGiga;			PowersOfGiga = new LargeInteger[upto];			int oldlen = old.Length;			if(oldlen > 0)				for(int i = 0; i < oldlen; i++) PowersOfGiga = old;			else {				PowersOfGiga[0] = 1;				oldlen = 1;			}			for(int i = oldlen; i < upto; i++) PowersOfGiga = PowersOfGiga[i - 1] * 1000000000;			Console.WriteLine("Gigas array filled up to 10^" + (9 * upto));		}				public String ToLongString(){ return ToLongString(true); }		public String ToLongString(bool punc){			bool neg = negative; negative = false;			LargeInteger li = Clone();			if(li.Exponent > li.Shift){				li.ExpandExponent(li.Exponent);				li.Expand(li.Shift);			} else {				li.Expand(li.Shift);				li.ExpandExponent(li.Exponent);			}			LargeInteger li_as_int = li.Clone();			int Log2 = li.Size * 32;			// Work with radix 10^9 to start with			int maxpower = (int)((Log2 * Math.Log10(2) / 9) + 1);			int[] digits = new int[maxpower + 1];						EnsureGigasFilled(maxpower + 1);						StringBuilder sb = new StringBuilder();			bool zero = true;			//Console.WriteLine("Starting display loop for "+li);			for(int i = maxpower; i >= 0; i--){				digits = (int)(li / PowersOfGiga).data[0];				li -= (digits * PowersOfGiga);								if(zero && (digits == 0) && (i > 0)) continue;				String thisblock = digits.ToString();				for(int j = 8; j >= 0; j--){					byte b = (byte)(digits / MiniPowers[j]);					digits -= (b * MiniPowers[j]);					if(zero && (b == 0)) continue;					else zero = false;					sb.Append(b);					if(punc && ((j % 3) == 0) && ((i + j) > 0)) sb.Append(',');				}				// Display in e notation if all zero and at least 9 places left				if(punc && (!zero) && (li == 0) && (i > 0)){					sb.Append("e" + (i * 9));					break;				}								//sb.Append('|');			}						if(zero) sb.Append('0');						if((Shift < 0) || (Exponent < 0)){				// Some fractional part				// Truncate to zero point				//li = Clone();			//Console.WriteLine("Starting fractional loop for li = "+li.ExpandExponent(li.Exponent));				li = this - li_as_int;				sb.Append('.');				int chars = 0, exp = 0;			 maxpower = (int)(((li.Size * 32) * Math.Log10(2) / 9) + 1);			 li.ExpandExponent(-(maxpower + li.Exponent));				bool stop = false;				do{					li *= 1000;					//int digit = (int)li.DoubleValue;					LargeInteger li2 = li.Clone();					int digit = (int)li2.ExpandExponent(li2.Exponent).Expand(li2.Shift).data[0];					li -= digit;					stop = li == 0;					if(zero && (digit != 0) && (chars > 3)){					 sb = new StringBuilder();						for(int j = 2; j >= 0; j--){							byte b = (byte)(digit / MiniPowers[j]);							zero &= (b == 0);							if(!zero) sb.Append(b);							digit -= (b * MiniPowers[j]);							if(stop && (digit == 0)) break;						}						sb.Append('.');					 exp = chars + 3;					 zero = false;					} else { 						if(digit != 0) zero = false;						for(int j = 2; j >= 0; j--){							byte b = (byte)(digit / MiniPowers[j]);							sb.Append(b);							digit -= (b * MiniPowers[j]);							if(stop && (digit == 0)) break;						}					}				} while((!stop) && ((chars += 3) < 1000));				if(exp > 0) sb.Append("e-"+exp);			}						negative = neg;			String s = sb.ToString();			if(s == "") s = "0";			if(neg) s = "-" + s;			return s;		}				public String StringRep(){			if((Shift | Exponent) == 0) return ToLongString(false);						String res = "`" + Size + "`" + Shift + "`" + Exponent + "`";			if(negative) res += "1`"; else res += "0`";			for(int i = 0; i < Size; i++) res += data.ToString("X8");						return res;		}				public LargeInteger Clone(){			LargeInteger r = this;			r.data = new uint[Size];			for(int i = 0; i < Size; i++) r.data = data;			return r;		}				public bool IsInteger {			get { return (Exponent == 0) && (Shift == 0) && (Size == 1); }		}				public uint UIntegerValue {			get {				LargeInteger li = Clone();				li.Expand(li.Shift); li.ExpandExponent(li.Exponent);				if(li.Size > 1) throw new OverflowException(ToString() + " is too large to be represented as an integer.");				else return li.data[0];			}		}				public int IntegerValue {			get { return (int)UIntegerValue; }		}				public UInt64 UInt64Value {			get {				LargeInteger li = Clone();				UInt64 u64 = 0;				li.Expand(li.Shift); li.ExpandExponent(li.Exponent);				if(li.Size > 2) throw new OverflowException(ToString() + " is too large to be represented as a 64-bit integer.");				else {					u64 = li.data[0];					if(li.Size == 2) u64 += (ulong)li.data[1] << 32;					return u64;				}			}		}				public Int64 Int64Value {			get { return (Int64)UInt64Value; }		}				public double DoubleValue {			get { 				double res = 0;				for(int i = 0; i < Size; i++)					res += data * Math.Pow(10, (Math.Log10(2) * ((i * 32) + Shift)) + Exponent);				if(negative) res = -res;				return res;			}		}				public LargeInteger Trim(){			int totrim = 0;			for(int i = Size - 1; i >= 0; i--, totrim++)				if(this.data != 0) break;			if(totrim == 0) return this;			if(totrim == Size) totrim--; // always leave one group!			uint[] data = new uint[Size - totrim];			for(int i = Size - totrim - 1; i >= 0; i--) data = this.data;			this.data = data;						return this;		}				public LargeInteger Expand(int bits){			Shift -= bits;			if(bits > 0)	this = ShiftLeft(bits);			else if(bits < 0) this = ShiftRight(-bits);			return this;		}				public LargeInteger ExpandExponent(int places){			//Console.Write("Expanding exp of "+this+" by "+places);			Exponent -= places;			if(places > 0) this = this * PowerOf10(places);			else if(places < 0) this = this / PowerOf10(-places);			//Console.WriteLine(" to "+this);			return this;		}				public LargeInteger Compress(){			// Reduce to the minimum number of bits while keeping accuracy			if(this == 0) return this;			//Console.WriteLine("Compressing "+this);			for(int shift = 0; ; shift++){				LargeInteger li = this.ShiftRight(shift);				if((li.data[0] % 2) == 1){					this.data = li.data;					Shift += shift;					break;				}			}			Trim();			return this;		}				public static LargeInteger PowerOf10(int power){			//if(power < 0) return new LargeInteger(1, power);			if(power < 0) throw new ArgumentException("Cannot raise to negative powers!");			EnsureGigasFilled((power / 9) + 1);			return PowersOfGiga[power / 9] * MiniPowers[power % 9];		}				public LargeInteger Abs(){			LargeInteger res = this;			res.negative = false;			return res;		}			}}


The only feature mine has that may be unusual is that it can represent non-integer values to arbitrary precision (but so can System.Decimal) and you can move the numbers left and right, both in base 10 and 2.

It also resizes itself to make itself as small as possible.

But if you're just doing 'sane' things Decimal will probably do the job.
jackolantern1
jackolantern1
Quote:
Original post by Conner McCloud
Quote:
Original post by joanusdmentia
Check out the System.Decimal type. It's still limited in size like the builtin types but the limit is ridiculously large, about 3 billion times larger than a 64-bit integer.

Quote:

The Decimal value type represents decimal numbers ranging from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. The Decimal value type is appropriate for financial calculations requiring large numbers of significant integral and fractional digits and no round-off errors.

Wow. If infinity were a number, I'll bet it would fit in a System.Decimal object.

CM


Wow. Just for anyone curious, that is 79 octillion. That is a large enough number to hold the mass of Earth in kilograms.

SiCrane
SiCrane
If you don't mind a dependency on the J# runtime there's a big number implementation in that. Details.
Mithrandir
Mithrandir
Quote:
Original post by turnpast
It looks like .NET 4 will have a big integer implementation in the standard libraries: BigInteger Structure.


I'm glad they put that back in. They originally had it in the 3.5 Beta 1 release, but then removed it in Beta 2. They never gave an official reason but I heard some hinting that they weren't happy with the arithmetic performance.
This is my signature. There are many like it, but this one is mine. My signature is my best friend. It is my life. I must master it as I must master my life. My signature, without me, is useless. Without my signature, I am useless.
Mike.Popoloski
Mike.Popoloski
Technically it's all still there in .NET 3.5, it's just been marked internal. You can pull the implementation out with Reflector if you feel the need [grin]
Mike Popoloski | Journal | SlimDX

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.