Original Post
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 )
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.
// 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; } }}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
Quote:
Original post by turnpast
It looks like .NET 4 will have a big integer implementation in the standard libraries: BigInteger Structure.
This topic has been locked by a moderator. New replies are not allowed.
With your permission, GameDev.net uses analytics cookies to understand how people use the platform. You can accept analytics or continue with necessary cookies only. Learn more