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); }
private static BigFloat Subtract(BigFloat a, BigFloat b, Boolean normalise) { a.Normalise(); b.Normalise(); a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if (a.IsZero && b.IsZero) { return(a); } if (a.Sign && !b.Sign) { b._sign = true; return(Add(a, b, normalise)); } if (!a.Sign && b.Sign) { a._sign = true; BigFloat added = Add(a, b, normalise); return((BigFloat)added.Negate()); } BigFloat result = new BigFloat(); a.AlignExponent(b); b.AlignExponent(a); result._exp = a._exp; Boolean wasSwapped = false; if (b.Length > a.Length) // then switch them around { BigFloat temp = a; a = b; b = temp; wasSwapped = true; } else { // if same length, check magnitude BigFloat a1 = (BigFloat)a.Absolute(); BigFloat b1 = (BigFloat)b.Absolute(); if (a1 < b1) { BigFloat temp = a; a = b; b = temp; wasSwapped = true; } else if (!(a1 > b1)) // i.e. equal { return(new BigFloat()); // return zero } } // Do work // it's a sad day when the preparation for an operation is just as long as the operation itself SByte digit = 0; SByte take = 0; for (int i = 0; i < b.Length; i++) { digit = (SByte)(a[i] - b[i] - take); if (digit < 0) { take = 1; digit = (SByte)(10 + digit); } else { take = 0; } result._data.Add(digit); } for (int i = b.Length; i < a.Length; i++) { digit = (SByte)(a[i] - take); if (digit < 0) { take = 1; digit = (SByte)(10 + digit); } else { take = 0; } result._data.Add(digit); } result._sign = a.Sign && b.Sign ? !wasSwapped : wasSwapped; /* if(normalise) * result.Normalise(); */ return(result); }
private static BigFloat Add(BigFloat a, BigFloat b, Boolean normalise) { a.Normalise(); b.Normalise(); a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if (a.IsZero && b.IsZero) { return(a); } if (a.Sign && !b.Sign) { b._sign = true; return(Subtract(a, b, normalise)); } if (!a.Sign && b.Sign) { b._sign = true; return(Subtract(b, a, normalise)); } BigFloat result = new BigFloat(); a.AlignExponent(b); b.AlignExponent(a); result._exp = a._exp; if (b.Length > a.Length) // then switch them around { BigFloat temp = a; a = b; b = temp; } // the work: // SByte digit = 0; SByte carry = 0; for (int i = 0; i < b.Length; i++) { digit = (SByte)((a[i] + b[i] + carry) % 10); carry = (SByte)((a[i] + b[i] + carry) / 10); result._data.Add(digit); } for (int i = b.Length; i < a.Length; i++) { digit = (SByte)((a[i] + carry) % 10); carry = (SByte)((a[i] + carry) / 10); result._data.Add(digit); } if (carry > 0) { result._data.Add(carry); } result._sign = a.Sign && b.Sign; /* if(normalise) // normalising shouldn't be necessary, but what the heck * result.Normalise(); */ return(result); }
private static BigFloat Subtract(BigFloat a, BigFloat b, Boolean normalise) { a.Normalise(); b.Normalise(); a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if( a.IsZero && b.IsZero ) return a; if( a.Sign && !b.Sign ) { b._sign = true; return Add(a, b, normalise); } if( !a.Sign && b.Sign ) { a._sign = true; BigFloat added = Add(a, b, normalise); return (BigFloat)added.Negate(); } BigFloat result = new BigFloat(); a.AlignExponent( b ); b.AlignExponent( a ); result._exp = a._exp; Boolean wasSwapped = false; if(b.Length > a.Length) { // then switch them around BigFloat temp = a; a = b; b = temp; wasSwapped = true; } else { // if same length, check magnitude BigFloat a1 = (BigFloat)a.Absolute(); BigFloat b1 = (BigFloat)b.Absolute(); if(a1 < b1) { BigFloat temp = a; a = b; b = temp; wasSwapped = true; } else if( !(a1 > b1) ) { // i.e. equal return new BigFloat(); // return zero } } // Do work // it's a sad day when the preparation for an operation is just as long as the operation itself SByte digit = 0; SByte take = 0; for(int i=0;i<b.Length;i++ ) { digit = (SByte)( a[i] - b[i] - take ); if( digit < 0 ) { take = 1; digit = (SByte)( 10 + digit ); } else { take = 0; } result._data.Add( digit ); } for(int i=b.Length;i<a.Length;i++ ) { digit = (SByte)( a[i] - take ); if( digit < 0 ) { take = 1; digit = (SByte)( 10 + digit ); } else { take = 0; } result._data.Add( digit ); } result._sign = a.Sign && b.Sign ? !wasSwapped : wasSwapped; /* if(normalise) result.Normalise(); */ return result; }
private static BigFloat Add(BigFloat a, BigFloat b, Boolean normalise) { a.Normalise(); b.Normalise(); a = (BigFloat)a.Clone(); b = (BigFloat)b.Clone(); if(a.IsZero && b.IsZero) return a; if(a.Sign && !b.Sign) { b._sign = true; return Subtract(a, b, normalise); } if(!a.Sign && b.Sign) { b._sign = true; return Subtract(b, a, normalise); } BigFloat result = new BigFloat(); a.AlignExponent( b ); b.AlignExponent( a ); result._exp = a._exp; if(b.Length > a.Length) { // then switch them around BigFloat temp = a; a = b; b = temp; } // the work: // SByte digit = 0; SByte carry = 0; for(int i=0;i<b.Length;i++) { digit = (SByte)( ( a[i] + b[i] + carry ) % 10 ); carry = (SByte)( ( a[i] + b[i] + carry ) / 10 ); result._data.Add( digit ); } for(int i=b.Length;i<a.Length;i++) { digit = (SByte)( ( a[i] + carry ) % 10 ); carry = (SByte)( ( a[i] + carry ) / 10 ); result._data.Add( digit ); } if( carry > 0 ) result._data.Add( carry ); result._sign = a.Sign && b.Sign; /* if(normalise) // normalising shouldn't be necessary, but what the heck result.Normalise(); */ return result; }
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; }