Exemplo n.º 1
0
        public static eeNumber operator *(eeNumber num1_orig, eeNumber num2_orig)
        {
            eeNumber num1 = num1_orig.Copy(),
                     num2 = num2_orig.Copy();

            // if either num is 0, return 0
            if (num1 == ZERO || num2 == ZERO)
            {
                return(new eeNumber(0));
            }

            bool negate = false;

            /* first account for negatives */
            // if either num is negative
            if (num1.negative ^ num2.negative)
            {
                // set both to non-negative to multiply them
                num1.negative = false;
                num2.negative = false;

                // apply negative afterwards
                negate = true;
            }
            else if (num1.negative && num2.negative)
            {
                // otherwise, negatives just cancel out
                num1.negative = false;
                num2.negative = false;
            }

            eeNumber final;

            // if only one num is a fraction
            if (num1.IsFrac() ^ num2.IsFrac())
            {
                eeNumber frac = num1.denominator != null ? num1 : num2,
                         reg  = num1.denominator != null ? num2 : num1;

                var den    = frac.PopDenominator();
                var newNum = (frac * reg) / den;

                final = newNum;
            }
            // if both nums are fractions
            else if (num1.IsFrac() && num2.IsFrac())
            {
                eeNumber frac1 = num1.PopDenominator(),
                         frac2 = num2.PopDenominator();

                final = (num1 * num2) / (frac1 * frac2);
            }
            // regular nums
            else
            {
                // Reverse because we're going from right to left.
                byte[] lhs = num1.bytes.Reverse().ToArray(),
                rhs = num2.bytes.Reverse().ToArray();

                // new digit
                eeNumber finalNum = new eeNumber(0);

                // foreach digit in on the top num
                for (int i = 0; i < rhs.Length; i++)
                {
                    byte        carry   = 0;
                    List <byte> product = new List <byte>();

                    // foreach digit in the bottom num
                    for (int j = 0; j < lhs.Length; j++)
                    {
                        // multiply them
                        byte digitProduct = (byte)(lhs[j] * rhs[i]);

                        if (carry != 0)
                        {
                            digitProduct += carry;
                            carry         = 0;
                        }

                        if (digitProduct > 9)
                        {
                            carry         = (byte)(digitProduct / 10);
                            digitProduct %= 10;
                        }

                        product.Add(digitProduct);
                    }

                    // If carry is left
                    if (carry != 0)
                    {
                        product.Add(carry);
                    }

                    product.Reverse();

                    // Add the needed amount of trailing zeros for place value
                    for (int z = 0; z < i; z++)
                    {
                        product.Add(0);
                    }

                    finalNum += new eeNumber(product.ToArray());
                }

                final = finalNum;
            }

            final.negative = negate;
            return(final);
        }
Exemplo n.º 2
0
        public static eeNumber operator /(eeNumber num1_orig, eeNumber num2_orig)
        {
            /* eeNumbers do not perform traditional division. That is only done
             * when the number needs to be approximated for a text representation.
             * For divison, we always keep the fractional form for arbitrary accuracy.
             */

            eeNumber num1 = num1_orig.Copy(),
                     num2 = num2_orig.Copy();

            if (num2 == ZERO)
            {
                throw new DivisionByZeroError(num1);
            }

            bool negate = false;

            /* first, account for negatives */
            // if either num is negative
            if (num1.negative ^ num2.negative)
            {
                // set both to non-negative to multiply them
                num1.negative = false;
                num2.negative = false;

                // apply negative afterwards
                negate = true;
            }
            else if (num1.negative && num2.negative)
            {
                // otherwise, negatives just cancel out
                num1.negative = false;
                num2.negative = false;
            }

            /* then, divide */
            bool a = num1.IsFrac(), b = num2.IsFrac();

            // frac divided by num
            if (a && !b)
            {
                num1.denominator *= num2;
                num1.negative     = negate;
                num1.Simplify();

                return(num1);
            }
            // num divided by num
            else if (!a && !b)
            {
                // check if right is a factor of left
                if (num1 > num2)
                {
                    var m = num1 % num2;
                    if (m == ZERO)
                    {
                        return(num1 % num2);
                    }
                }

                num1.denominator = num2;
                num1.negative    = negate;
                num1.Simplify();

                return(num1);
            }
            // num divided by frac
            else if (!a && b)
            {
                eeNumber numerator   = num1 * num2.denominator;
                eeNumber denominator = num2;

                var newNum = numerator / denominator;
                newNum.negative = negate;
                return(newNum);
            }
            // frac divided by frac
            else
            {
                var denom1 = num1.PopDenominator();

                eeNumber numerator   = num1 * num2.PopDenominator();
                eeNumber denominator = num2 * denom1;

                var newNum = numerator / denominator;
                newNum.negative = negate;
                return(newNum);
            }
        }
Exemplo n.º 3
0
        // Warning: Subtraction will destroy the contents of num2 and set the contents of num1 to the result
        // Make sure to pass a copy of num2 if you are keeping its value
        public static eeNumber operator -(eeNumber num1_orig, eeNumber num2_orig)
        {
            eeNumber num1 = num1_orig.Copy(),
                     num2 = num2_orig.Copy();

            // If either number is a fraction, cross multiply
            if (num1.IsFrac() || num2.IsFrac())
            {
                eeNumber frac1 = num1.PopDenominator(),
                         frac2 = num2.PopDenominator();

                num1 *= frac2;
                num2 *= frac1;

                var ret = (num1 - num2) / (frac1 * frac2);

                ret.TrimZeros();
                ret.Simplify();

                return(ret);
            }

            // if the two nums are the same
            if (num1 == num2)
            {
                return(ZERO.Copy());
            }
            // if first num is negative
            else if (num1.negative && !num2.negative)
            {
                // add them then negate it
                num1.negative = false;
                var sum = num1 + num2;
                sum.negative = true;
                return(sum);
            }
            // if second num is negative
            else if (num2.negative && !num1.negative)
            {
                // minus and negatives cancel
                num2.negative = false;
                return(num1 + num2);
            }
            // If they're both negative
            else if (num1.negative && num2.negative)
            {
                // Treat this as adding a negative to a positive
                num2.negative = false;
                return(num1 + num2);
            }

            // If we're going to get a negative answer
            bool negate = false;

            if (num2 > num1)
            {
                // reverse the two
                var buf = num1;
                num1 = num2;
                num2 = buf;

                // and negate
                negate = true;
            }

            // Reverse because we're subtracting from right to left.
            byte[] l_bytes = num1.bytes.Reverse().ToArray(),
            r_bytes = num2.bytes.Reverse().ToArray();

            bool carry = false;
            int  i;

            for (i = 0; i < r_bytes.Length; i++)
            {
                // Account for the previous carry
                if (carry)
                {
                    r_bytes[i]++;
                    carry = false;
                }

                // Subtract the digits
                byte digitDiff;
                if (l_bytes[i] < r_bytes[i]) // account for carry
                {
                    digitDiff = (byte)((10 + l_bytes[i]) - r_bytes[i]);
                    carry     = true;
                }
                else
                {
                    digitDiff = (byte)(l_bytes[i] - r_bytes[i]);
                }

                // Set the digit
                l_bytes[i] = digitDiff;
            }


            // If there is still carry left
            while (carry)
            {
                // subtract one from the next value
                if (l_bytes[i] == 0)
                {
                    l_bytes[i] = 9;
                    i++;
                }
                else
                {
                    l_bytes[i] -= 1;
                    carry       = false;
                }
            }

            // Put it in order again
            l_bytes = l_bytes.Reverse().ToArray();

            num1.bytes    = l_bytes;
            num1.negative = negate;
            num1.TrimZeros();

            return(num1);
        }