public static BigFloat Multiply(BigFloat a, BigFloat b) { a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if (b.Length > a.Length) // then switch them around { BigFloat temp = a; a = b; b = temp; } BigFloat retval = new BigFloat(); List <BigFloat> rows = new List <BigFloat>(); retval._sign = a.Sign == b.Sign; retval._exp = a._exp + b._exp; // for each digit in b for (int i = 0; i < b.Length; i++) { BigFloat row = new BigFloat(); row._exp = retval._exp; Int32 digit = 0, carry = 0; for (int exp = 0; exp < i; exp++) { row._data.Add(0); // pad with zeros to the right } for (int j = 0; j < a.Length; j++) // perform per-digit multiplication of a against b { digit = a[j] * b[i] + carry; carry = digit / 10; digit = digit % 10; row._data.Add((SByte)digit); } // reduce the carry while (carry > 0) { digit = carry % 10; carry = carry / 10; row._data.Add((SByte)digit); } rows.Add(row); } // sum the rows to give the result foreach (BigFloat row in rows) { retval = (BigFloat)retval.Add(row); } retval.Normalise(); return(retval); }
public static BigFloat Divide(BigFloat dividend, BigFloat divisor, out Boolean isExact) { if (divisor.IsZero) { throw new DivideByZeroException(); } isExact = true; if (dividend.IsZero) { return((BigFloat)dividend.Clone()); } /////////////////////////////// BigFloat quotient = new BigFloat(); quotient._sign = dividend.Sign == divisor.Sign; dividend = (BigFloat)dividend.Absolute(); divisor = (BigFloat)divisor.Absolute(); BigFloat aPortion; BigFloat bDigit = null; ////////////////////////////// while (divisor[0] == 0) // remove least-significant zeros and up the exponent to compensate { divisor._exp++; divisor._data.RemoveAt(0); } quotient._exp = dividend.Length + dividend._exp - divisor.Length - divisor._exp + 1; dividend._exp = 0; divisor._exp = 0; aPortion = new BigFloat(); Int32 bump = 0, c = -1; Boolean hump = false; isExact = false; while (quotient.Length < _divisionDigits) // abandon hope all ye who enter here { aPortion = dividend.Msd(divisor.Length + (hump ? 1 : 0)); if (aPortion < divisor) { int i = 1; while (aPortion < divisor) { aPortion = dividend.Msd(divisor.Length + i + (hump ? 1 : 0)); quotient._exp--; quotient._data.Add(0); i++; } hump = true; } bDigit = 0; //tt = 0; c = 0; while (bDigit < aPortion) { bDigit = (BigFloat)bDigit.Add(divisor); //tt += b; c++; } if (bDigit != aPortion) { c--; bDigit = new BigFloat(c); bDigit = (BigFloat)bDigit.Multiply(divisor); //tt *= b; isExact = false; } else { isExact = true; } quotient._data.Add((sbyte)c); quotient._exp--; aPortion.Normalise(); dividend.Normalise(); bump = aPortion.Length - bDigit.Length; if (aPortion.Length > dividend.Length) { dividend = aPortion; } bDigit = bDigit.Msd(dividend.Length - bump); aPortion = BigFloat.Add(dividend, (BigFloat)bDigit.Negate(), false); dividend = (BigFloat)aPortion.Clone(); if (aPortion.IsZero) { break; // no more work necessary } if (hump) { if (dividend[dividend.Length - 1] == 0) { dividend._data.RemoveAt(dividend.Length - 1); } } if (dividend[dividend.Length - 1] == 0) { dividend._data.RemoveAt(dividend.Length - 1); while (dividend[dividend.Length - 1] == 0) { quotient._exp--; quotient._data.Add(0); dividend._data.RemoveAt(dividend.Length - 1); if (dividend.Length == 0) { break; } } if (dividend.Length == 0) { break; } hump = false; } else { hump = true; } if (quotient.Length == 82) { c = 0; } } quotient._data.Reverse(); quotient.Normalise(); return(quotient); }
protected override BigNum Add(BigNum other) { return(BigFloat.Add(this, (BigFloat)other)); }
public static BigFloat Multiply(BigFloat a, BigFloat b) { a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if(b.Length > a.Length) { // then switch them around BigFloat temp = a; a = b; b = temp; } BigFloat retval = new BigFloat(); List<BigFloat> rows = new List<BigFloat>(); retval._sign = a.Sign == b.Sign; retval._exp = a._exp + b._exp; // for each digit in b for(int i=0;i<b.Length;i++) { BigFloat row = new BigFloat(); row._exp = retval._exp; Int32 digit = 0, carry = 0; for(int exp=0;exp<i;exp++) row._data.Add( 0 ); // pad with zeros to the right for(int j=0;j<a.Length;j++) { // perform per-digit multiplication of a against b digit = a[j] * b[i] + carry; carry = digit / 10; digit = digit % 10; row._data.Add( (SByte)digit ); } // reduce the carry while(carry > 0) { digit = carry % 10; carry = carry / 10; row._data.Add( (SByte)digit ); } rows.Add( row ); } // sum the rows to give the result foreach(BigFloat row in rows) { retval = (BigFloat)retval.Add(row); } retval.Normalise(); return retval; }