Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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;
        }
Пример #6
0
        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;
        }
Пример #7
0
        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;
        }
Пример #8
0
        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;
        }