Пример #1
0
 public BigRational(BigFloat num)
     : this(num.ToString())
 {
     // rather than use any implementation-specific method of getting the integer and non-int part of the number just use the string representation
 }
Пример #2
0
        private BigFloat GetFractionalPart()
        {
            if(_exp == 0) return 0;

            Normalise();

            BigFloat retVal = new BigFloat();
            for(int i=0;i<Length && i<-_exp;i++) { // get all the digits to the right of the radix point
                retVal._data.Add( this[i] );
            }
            retVal._exp = _exp;

            return retVal;
        }
Пример #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
        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);
        }
Пример #5
0
 protected internal override BigNum Floor()
 {
     return(BigFloat.Subtract(this, GetFractionalPart()));
 }
Пример #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 override BigNum Clone()
 {
     BigFloat dolly = new BigFloat();
     dolly._sign = Sign;
     dolly._exp = _exp;
     dolly._data.AddRange( _data );
     return dolly;
 }
Пример #8
0
 protected override BigNum Multiply(BigNum multiplicand)
 {
     return(BigFloat.Multiply(this, (BigFloat)multiplicand));
 }
Пример #9
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;
        }
Пример #10
0
 public static BigFloat Subtract(BigFloat a, BigFloat b)
 {
     return Subtract(a, b, true);
 }
Пример #11
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;
        }
Пример #12
0
 public static BigFloat Divide(BigFloat dividend, BigFloat divisor)
 {
     Boolean wasExact;
     return Divide(dividend, divisor, out wasExact);
 }
Пример #13
0
 // there really needs to be a new feature in OOP where interfaces can define static methods without having to use factory classes or the singleton pattern
 public static BigFloat Add(BigFloat a, BigFloat b)
 {
     return Add(a, b, true);
 }
Пример #14
0
 /// <summary>Nabs the most significant digits of this number. If <paramref name="count" /> is greater than the length of the number it pads zeros.</summary>
 /// <param name="count">Number of digits to return</param>
 private BigFloat Msd(Int32 count)
 {
     BigFloat retVal = new BigFloat();
     if(count > Length) {
     /*				Int32 i = 0;
         while( i < count - Length) {
             retVal._data.Add(0);
             i++;
         }*/
         for(int i=0;i<count-Length;i++) {
             retVal._data.Add( 0 );
         }
         count = Length;
     }
     for(int i=0;i<count;i++) {
         retVal._data.Add( this[Length - count + i] );
     }
     return retVal;
 }
Пример #15
0
        public Int32 CompareTo(BigFloat o)
        {
            if( Equals(o) ) return 0;

            if(Sign && !o.Sign) return 1;
            else if(!Sign && !o.Sign) return -1;

            AlignExponent(o);
            o.AlignExponent(this);

            Int32 expDifference = ( _exp + _data.Count ) - ( o._exp + o._data.Count );
            if(expDifference > 0) return 1;
            else if(expDifference < 0) return -1;

            // by now both will have the same length
            for(int i=Length-1;i>=0;i--) {
                if( this[i] > o[i] ) return 1;
                if( this[i] < o[i] ) return -1;
            }

            return 0;
        }
Пример #16
0
 protected override BigNum Add(BigNum other)
 {
     return(BigFloat.Add(this, (BigFloat)other));
 }
Пример #17
0
        public override Boolean Equals(Object obj)
        {
            // remember, this is value equality and two BigNums (even if they're of different subclass) can have an equal value
            if( obj == null ) return false;

            if( obj is BigNum ) {
                BigFloat bn = obj as BigFloat;
                return bn == null ? false : Equals( bn );
            }

            String s = obj.ToString();
            BigFloat b = new BigFloat( s );

            return Equals( b );
        }
Пример #18
0
 protected override BigNum Divide(BigNum divisor)
 {
     return(BigFloat.Divide(this, (BigFloat)divisor));
 }
Пример #19
0
        public Boolean Equals(BigFloat other)
        {
            if( other == null ) return false;
            if(Object.ReferenceEquals(this, other)) return true;

            if(Sign != other.Sign) return false;
            if(_exp != other._exp) return false;
            if(Length != other.Length) return false;

            for(int i=0;i<Length;i++) {
                if(this[i] != other[i]) return false;
            }

            return true;
        }
Пример #20
0
        // there really needs to be a new feature in OOP where interfaces can define static methods without having to use factory classes or the singleton pattern

        public static BigFloat Add(BigFloat a, BigFloat b)
        {
            return(Add(a, b, true));
        }
Пример #21
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;
        }
Пример #22
0
 public static BigFloat Subtract(BigFloat a, BigFloat b)
 {
     return(Subtract(a, b, true));
 }
Пример #23
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;
        }
Пример #24
0
        public static BigFloat Divide(BigFloat dividend, BigFloat divisor)
        {
            Boolean wasExact;

            return(Divide(dividend, divisor, out wasExact));
        }
Пример #25
0
 /// <summary>Makes the exponent values of both numbers equal by padding zeros.</summary>
 private void AlignExponent(BigFloat withThis)
 {
     while( _exp > withThis._exp ) {
         _exp--;
         _data.Insert( 0, 0 );
     }
 }
Пример #26
0
 public BigRational(BigFloat num) : this(num.ToString())
 {
     // rather than use any implementation-specific method of getting the integer and non-int part of the number just use the string representation
 }
Пример #27
0
        public BigFloat Evaluate()
        {
            BigFloat num = new BigFloat( _num.ToString() );
            BigFloat den = new BigFloat( _den.ToString() );

            return (BigFloat)(num / den);
        }