Inheritance: IComparable, IFormattable
Exemple #1
0
        public void Main()
        {
            Fraction frac = new Fraction(); // we'll get NaN
            Assert.AreEqual(frac, Fraction.NaN);
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.NaNSymbol);

            frac = new Fraction(1, 5);       // we'll get 1/5
            Assert.AreEqual(frac.ToString(), "1/5");

            frac = new Fraction(25);        // we'll get 25
            Assert.AreEqual(frac.ToString(), "25");

            frac = new Fraction(0.0);		// we'll get 0
            Assert.AreEqual(frac.ToString(), "0");

            frac = new Fraction(0.25);      // we'll get 1/4
            Assert.AreEqual(frac.ToString(), "1/4");

            frac = new Fraction(9.25);      // we'll get 37/4
            Assert.AreEqual(frac.ToString(), "37/4");

            frac = new Fraction(long.MaxValue, 1);
            string compareTo = string.Format("{0}", long.MaxValue);
            Assert.AreEqual(frac.ToString(), compareTo);

            frac = new Fraction(1, long.MaxValue);
            compareTo = string.Format("1/{0}", long.MaxValue);
            Assert.AreEqual(frac.ToString(), compareTo);

            frac = new Fraction(long.MaxValue, long.MaxValue);
            Assert.AreEqual(frac.ToString(), "1");

            // the plus-one issue is because of twos-complement representing one more negtive value than
            // positive
            frac = new Fraction(long.MinValue + 1, 1);
            compareTo = string.Format("{0}", long.MinValue + 1);
            Assert.AreEqual(frac.ToString(), compareTo);

            frac = new Fraction(1, long.MinValue + 1);
            compareTo = string.Format("-1/{0}", Math.Abs(long.MinValue + 1));
            Assert.AreEqual(frac.ToString(), compareTo);

            frac = new Fraction(long.MinValue + 1, long.MinValue + 1);
            Assert.AreEqual(frac.ToString(), "1");

            frac = new Fraction(long.MaxValue, long.MinValue + 1);
            Assert.AreEqual(frac.ToString(), "-1");

            frac = new Fraction(long.MinValue + 1, long.MaxValue);
            Assert.AreEqual(frac.ToString(), "-1");

            frac = new Fraction(0.025);     // we'll get 1/40
            Assert.AreEqual(frac.ToString(), "1/40");

            frac = new Fraction(1 / 2.0);   // we'll get 1/2
            Assert.AreEqual(frac.ToString(), "1/2");
            frac = new Fraction(1 / 3.0);   // we'll get 1/3
            Assert.AreEqual(frac.ToString(), "1/3");
            frac = new Fraction(1 / 4.0);   // we'll get 1/4
            Assert.AreEqual(frac.ToString(), "1/4");
            frac = new Fraction(1 / 5.0);   // we'll get 1/5
            Assert.AreEqual(frac.ToString(), "1/5");
            frac = new Fraction(1 / 6.0);   // we'll get 1/6
            Assert.AreEqual(frac.ToString(), "1/6");
            frac = new Fraction(1 / 7.0);   // we'll get 1/7
            Assert.AreEqual(frac.ToString(), "1/7");
            frac = new Fraction(1 / 8.0);   // we'll get 1/8
            Assert.AreEqual(frac.ToString(), "1/8");
            frac = new Fraction(1 / 9.0);   // we'll get 1/9
            Assert.AreEqual(frac.ToString(), "1/9");
            frac = new Fraction(1 / 10.0);   // we'll get 1/10
            Assert.AreEqual(frac.ToString(), "1/10");
            frac = new Fraction(1 / 49.0);   // we'll get 1/49
            Assert.AreEqual(frac.ToString(), "1/49");

            frac = new Fraction(6);
            Assert.AreEqual(frac.ToString(), "6");

            Fraction divisor = new Fraction(4);
            Assert.AreEqual(divisor.ToString(), "4");

            frac %= divisor;
            Assert.AreEqual(frac.ToString(), "2");

            frac = new Fraction(9, 4);
            Assert.AreEqual(frac.ToString(), "9/4");

            divisor = new Fraction(2);
            Assert.AreEqual(divisor.ToString(), "2");

            frac %= divisor;
            Assert.AreEqual(frac.ToString(), "1/4");

            frac = new Fraction(5, 12);
            Assert.AreEqual(frac.ToString(), "5/12");

            divisor = new Fraction(1, 4);
            Assert.AreEqual(divisor.ToString(), "1/4");

            frac %= divisor;
            Assert.AreEqual(frac.ToString(), "1/6");

            frac = new Fraction(1.0);     // we'll get 1
            Assert.AreEqual(frac.ToString(), "1");

            frac = new Fraction(2.0);     // we'll get 2
            Assert.AreEqual(frac.ToString(), "2");

            frac = new Fraction(-2.0);    // we'll get -2
            Assert.AreEqual(frac.ToString(), "-2");

            frac = new Fraction(-1.0);    // we'll get -1
            Assert.AreEqual(frac.ToString(), "-1");

            frac = new Fraction(0.5);		// we'll get 1/2
            Assert.AreEqual(frac.ToString(), "1/2");

            frac = new Fraction(1.5);     // we'll get 3/2
            Assert.AreEqual(frac.ToString(), "3/2");

            Console.WriteLine("Doing the loop check");
            for (int numerator = -100; numerator < 100; numerator++)
            {
                Console.Write("{0} ", numerator);

                for (int denominator = -100; denominator < 100; denominator++)
                {
                    Fraction frac1 = new Fraction(numerator, denominator);

                    double dbl = (double)numerator / (double)denominator;
                    Fraction frac2 = new Fraction(dbl);

                    Assert.AreEqual(frac1, frac2);
                }
            }
            Console.WriteLine();

            frac = new Fraction("6.25");    // we'll get 25/4
            Assert.AreEqual(frac.ToString(), "25/4");

            frac = 0;
            Assert.AreEqual(frac.ToString(), "0");

            frac = 1;
            Assert.AreEqual(frac.ToString(), "1");

            frac /= new Fraction(0);
            Assert.AreEqual(frac, Fraction.PositiveInfinity);
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.PositiveInfinitySymbol);

            frac = -1;
            Assert.AreEqual(frac.ToString(), "-1");

            frac /= new Fraction(0);
            Assert.AreEqual(frac, Fraction.NegativeInfinity);
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.NegativeInfinitySymbol);

            // we can enter anything like "213" or
            // "23/3" or "4.27"
            Console.Write("Enter a Fraction: ");
            frac = new Fraction(System.Console.ReadLine());

            Console.WriteLine(frac);     // displays the current value of frac object;

            frac = new Fraction("1/2"); // initialize a fraction with 1/2
            Assert.AreEqual(frac.ToString(), "1/2");

            Console.WriteLine(frac + 2.5);     // will display 3
            Assert.AreEqual((frac + 2.5).ToString(), "3");

            frac = "1/2";			// implicit cast from string to
            Assert.AreEqual(frac.ToString(), "1/2");

            frac = "22.5";         // implicit cast from string to fraction
            Assert.AreEqual(frac.ToString(), "45/2");

            frac = 10.25;         // implicit cast from double to fraction
            Assert.AreEqual(frac.ToString(), "41/4");

            frac = 15;             // implicit cast from integer/long to fraction
            Assert.AreEqual(frac.ToString(), "15");

            frac = 0.5;                 // initialize frac=1/2
            Assert.AreEqual(frac.ToString(), "1/2");

            Console.WriteLine(frac - 0.25);    // Yes, you are right. "1/4" is displayed
            Assert.AreEqual((frac - 0.25).ToString(), "1/4");

            Console.WriteLine(frac + "1/4");
            Assert.AreEqual((frac + "1/4").ToString(), "3/4");

            if (frac.Equals(0.5))
                Console.WriteLine("seems that frac == 0.5");

            frac += 0.5;
            Assert.AreEqual(frac.ToString(), "1");

            if (frac.Equals(1))
                Console.WriteLine("seems that now frac == 1");

            frac = double.NaN;
            Console.WriteLine(frac.ToString());
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.NaNSymbol);

            frac = double.PositiveInfinity;
            Console.WriteLine(frac.ToString());
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.PositiveInfinitySymbol);

            frac = double.NegativeInfinity;
            Console.WriteLine(frac.ToString());
            Assert.AreEqual(frac.ToString(), NumberFormatInfo.CurrentInfo.NegativeInfinitySymbol);

            frac = "33";
            frac += "1/3";
            Console.WriteLine(frac.ToString());

            frac *= 3;
            Console.WriteLine(frac.ToString());

            Console.Write("Any key to quit");
            Console.ReadLine();
        }
Exemple #2
0
        /// <summary>
        /// Compares this Fraction to another Fraction
        /// </summary>
        /// <param name="right">The Fraction to compare against</param>
        /// <returns>-1 if this is less than <paramref name="right"></paramref>,
        ///  0 if they are equal,
        ///  1 if this is greater than <paramref name="right"></paramref></returns>
        public int CompareTo(Fraction right)
        {
            // if left is an indeterminate, punt to the helper...
            if (this.m_Denominator == 0)
            {
                return IndeterminantCompare(NormalizeIndeterminate(this.m_Numerator), right);
            }

            // if right is an indeterminate, punt to the helper...
            if (right.m_Denominator == 0)
            {
                // note sign-flip...
                return -IndeterminantCompare(NormalizeIndeterminate(right.m_Numerator), this);
            }

            // they're both normal Fractions
            Fraction localThis = new Fraction(this);
            Fraction localRight = new Fraction(right);
            CrossReducePair(localThis, localRight);

            try
            {
                checked
                {
                    long leftScale = localThis.m_Numerator * localRight.m_Denominator;
                    long rightScale = localThis.m_Denominator * localRight.m_Numerator;

                    if (leftScale < rightScale)
                        return -1;
                    else if (leftScale > rightScale)
                        return 1;
                    else
                        return 0;
                }
            }
            catch (Exception e)
            {
                throw new FractionException(string.Format("CompareTo({0}, {1}) error", this, right), e);
            }
        }
Exemple #3
0
        /// <summary>
        /// Inverts a Fraction
        /// </summary>
        /// <returns>The inverted Fraction (with Denominator over Numerator)</returns>
        /// <remarks>Does NOT throw for zero Numerators as later use of the fraction will catch the error.</remarks>
        public Fraction Inverse()
        {
            // don't use the obvious constructor because we do not want it normalized at this time
            Fraction frac = new Fraction();

            frac.m_Numerator = this.m_Denominator;
            frac.m_Denominator = this.m_Numerator;
            return frac;
        }
Exemple #4
0
 /// <summary>
 /// Creates an inverted Fraction
 /// </summary>
 /// <returns>The inverted Fraction (with Denominator over Numerator)</returns>
 /// <remarks>Does NOT throw for zero Numerators as later use of the fraction will catch the error.</remarks>
 public static Fraction Inverted(double value)
 {
     Fraction frac = new Fraction(value);
     return frac.Inverse();
 }
Exemple #5
0
        /// <summary>
        /// Reduces (simplifies) a Fraction by dividing down to lowest possible denominator (via GCD)
        /// </summary>
        /// <param name="frac">The Fraction to be reduced [WILL BE MODIFIED IN PLACE]</param>
        /// <remarks>Modifies the input arguments in-place! Will normalize the NaN and infinites
        /// representation. Will set Denominator to 1 for any zero numerator. Moves sign to the
        /// Numerator.</remarks>
        /// <example>2/4 will be reduced to 1/2</example>
        public static void ReduceFraction(Fraction frac)
        {
            // clean up the NaNs and infinites
            if (frac.m_Denominator == 0)
            {
                frac.m_Numerator = (long)NormalizeIndeterminate(frac.m_Numerator);
                return;
            }

            // all forms of zero are alike.
            if (frac.m_Numerator == 0)
            {
                frac.m_Denominator = 1;
                return;
            }

            long iGCD = GCD(frac.m_Numerator, frac.m_Denominator);
            frac.m_Numerator /= iGCD;
            frac.m_Denominator /= iGCD;

            // if negative sign in denominator
            if (frac.m_Denominator < 0)
            {
                //move negative sign to numerator
                frac.m_Numerator = -frac.m_Numerator;
                frac.m_Denominator = -frac.m_Denominator;
            }
        }
Exemple #6
0
 /// <summary>
 /// Construct a Fraction from another fraction
 /// </summary>
 public Fraction(Fraction f)
 {
     this.m_Numerator = f.Numerator;
     this.m_Denominator = f.Denominator;
 }
Exemple #7
0
        /*
        /// <summary>
        /// Reduces (simplifies) a Fraction by dividing down to lowest possible denominator (via GCD)
        /// </summary>
        /// <param name="frac">The Fraction to be reduced</param>
        /// <returns>Will normalize the NaN and infinites representation.
        /// Will set Denominator to 1 for any zero numerator.
        /// Moves sign to the Numerator.</returns>
        /// <example>2/4 will be reduced to 1/2</example>
        public static Fraction ReduceFraction(Fraction frac)
        {
            Fraction reducedFraction = new Fraction(frac);

            // clean up the NaNs and infinites
            if (frac.m_Denominator == 0)
            {
                reducedFraction.m_Numerator = (long)NormalizeIndeterminate(frac.m_Numerator);
                return reducedFraction;
            }

            // all forms of zero are alike.
            if (frac.m_Numerator == 0)
            {
                reducedFraction.m_Denominator = 1;
                return reducedFraction;
            }

            long iGCD = GCD(frac.m_Numerator, frac.m_Denominator);
            reducedFraction.m_Numerator /= iGCD;
            reducedFraction.m_Denominator /= iGCD;

            // if negative sign in denominator
            if (frac.m_Denominator < 0)
            {
                //move negative sign to numerator
                reducedFraction.m_Numerator = -frac.m_Numerator;
                reducedFraction.m_Denominator = -frac.m_Denominator;
            }

            return reducedFraction;
        }
         */
        /// <summary>
        /// Cross-reduces a pair of Fractions so that we have the best GCD-reduced values for multiplication
        /// </summary>
        /// <param name="frac1">The first Fraction [WILL BE MODIFIED IN PLACE]</param>
        /// <param name="frac2">The second Fraction [WILL BE MODIFIED IN PLACE]</param>
        /// <remarks>Modifies the input arguments in-place!</remarks>
        /// <example>(3/4, 5/9) = (1/4, 5/3)</example>
        public static void CrossReducePair(Fraction frac1, Fraction frac2)
        {
            // leave the indeterminates alone!
            if (frac1.m_Denominator == 0 || frac2.m_Denominator == 0)
                return;

            long gcdTop = GCD(frac1.m_Numerator, frac2.m_Denominator);
            frac1.m_Numerator = frac1.m_Numerator / gcdTop;
            frac2.m_Denominator = frac2.m_Denominator / gcdTop;

            long gcdBottom = GCD(frac1.m_Denominator, frac2.m_Numerator);
            frac2.m_Numerator = frac2.m_Numerator / gcdBottom;
            frac1.m_Denominator = frac1.m_Denominator / gcdBottom;
        }
Exemple #8
0
 /// <summary>
 /// Negates the Fraction
 /// </summary>
 /// <param name="frac">Value to negate</param>
 /// <returns>A new Fraction that is sign-flipped from the input</returns>
 private static Fraction Negate(Fraction frac)
 {
     // for a NaN, it's still a NaN
     return new Fraction(-frac.m_Numerator, frac.m_Denominator);
 }
Exemple #9
0
        /// <summary>
        /// Compares for equality the current Fraction to the value passed.
        /// </summary>
        /// <param name="right">A Fraction to compare against</param>
        /// <param name="notEqualCheck">If true, we're looking for not-equal</param>
        /// <returns>True if the <paramref name="right"></paramref> equals the current 
        /// fraction, false otherwise. If comparing two NaNs, they are always equal AND
        /// not-equal.</returns>
        private bool CompareEquality(Fraction right, bool notEqualCheck)
        {
            // insure we're normalized first
            ReduceFraction(this);

            // now normalize the comperand
            ReduceFraction(right);

            if (this.m_Numerator == right.m_Numerator && this.m_Denominator == right.m_Denominator)
            {
                // special-case rule, two NaNs are always both equal
                if (notEqualCheck && this.IsNaN())
                    return true;
                else
                    return !notEqualCheck;
            }
            else
            {
                return notEqualCheck;
            }
        }
Exemple #10
0
        /// <summary>
        /// Multiplies two Fractions
        /// </summary>
        /// <param name="left">A Fraction</param>
        /// <param name="right">Another Fraction</param>
        /// <returns>Product of the Fractions. Returns NaN if either Fraction is a NaN.</returns>
        /// <exception cref="FractionException">Will throw if an overflow occurs. Does a cross-reduce to 
        /// insure only the unavoidable overflows occur.</exception>
        private static Fraction Multiply(Fraction left, Fraction right)
        {
            if (left.IsNaN() || right.IsNaN())
                return NaN;
            Fraction localLeft = new Fraction(left);
            Fraction localRight = new Fraction(right);
            CrossReducePair(localLeft, localRight);

            try
            {
                checked
                {
                    long numerator = localLeft.m_Numerator * localRight.m_Numerator;
                    long denominator = localLeft.m_Denominator * localRight.m_Denominator;

                    return new Fraction(numerator, denominator);
                }
            }
            catch (Exception e)
            {
                throw new FractionException("Multiply error", e);
            }
        }
Exemple #11
0
        /// <summary>
        /// Returns the modulus (remainder after dividing) two Fractions
        /// </summary>
        /// <param name="left">A Fraction</param>
        /// <param name="right">Another Fraction</param>
        /// <returns>Modulus of the Fractions. Returns NaN if either Fraction is a NaN.</returns>
        /// <exception cref="FractionException">Will throw if an overflow occurs. Does a cross-reduce to 
        /// insure only the unavoidable overflows occur.</exception>
        private static Fraction Modulus(Fraction left, Fraction right)
        {
            if (left.IsNaN() || right.IsNaN())
                return NaN;

            try
            {
                checked
                {
                    // this will discard any fractional places...
                    Int64 quotient = (Int64)(left / right);
                    Fraction whole = new Fraction(quotient * right.m_Numerator, right.m_Denominator);
                    return left - whole;
                }
            }
            catch (Exception e)
            {
                throw new FractionException("Modulus error", e);
            }
        }
Exemple #12
0
        /// <summary>
        /// Determines how this Fraction, of an indeterminate type, compares to another Fraction
        /// </summary>
        /// <param name="leftType">What kind of indeterminate</param>
        /// <param name="right">The other Fraction to compare against</param>
        /// <returns>-1 if this is less than <paramref name="right"></paramref>,
        ///  0 if they are equal,
        ///  1 if this is greater than <paramref name="right"></paramref></returns>
        /// <remarks>NaN is less than anything except NaN and Negative Infinity. Negative Infinity is less
        /// than anything except Negative Infinity. Positive Infinity is greater than anything except
        /// Positive Infinity.</remarks>
        private static int IndeterminantCompare(Indeterminates leftType, Fraction right)
        {
            switch (leftType)
            {
                case Indeterminates.NaN:
                    // A NaN is...
                    if (right.IsNaN())
                        return 0;	// equal to a NaN
                    else if (right.IsNegativeInfinity())
                        return 1;	// great than Negative Infinity
                    else
                        return -1;	// less than anything else

                case Indeterminates.NegativeInfinity:
                    // Negative Infinity is...
                    if (right.IsNegativeInfinity())
                        return 0;	// equal to Negative Infinity
                    else
                        return -1;	// less than anything else

                case Indeterminates.PositiveInfinity:
                    if (right.IsPositiveInfinity())
                        return 0;	// equal to Positive Infinity
                    else
                        return 1;	// greater than anything else

                default:
                    // this CAN'T happen, something VERY wrong is going on...
                    return 0;
            }
        }
Exemple #13
0
        /// <summary>
        /// Adds two Fractions
        /// </summary>
        /// <param name="left">A Fraction</param>
        /// <param name="right">Another Fraction</param>
        /// <returns>Sum of the Fractions. Returns NaN if either Fraction is a NaN.</returns>
        /// <exception cref="FractionException">Will throw if an overflow occurs when computing the
        /// GCD-normalized values.</exception>
        private static Fraction Add(Fraction left, Fraction right)
        {
            if (left.IsNaN() || right.IsNaN())
                return NaN;

            long gcd = GCD(left.m_Denominator, right.m_Denominator); // cannot return less than 1
            long leftDenominator = left.m_Denominator / gcd;
            long rightDenominator = right.m_Denominator / gcd;

            try
            {
                checked
                {
                    long numerator = left.m_Numerator * rightDenominator + right.m_Numerator * leftDenominator;
                    long denominator = leftDenominator * rightDenominator * gcd;

                    return new Fraction(numerator, denominator);
                }
            }
            catch (Exception e)
            {
                throw new FractionException("Add error", e);
            }
        }
Exemple #14
0
        private static List<Ingredient> ExtractIngredients(HtmlNode ingredientsNode)
        {
            List<Ingredient> ingredients = new List<Ingredient>();

            string[] ingredientLines = ingredientsNode.InnerHtml.Split(new string[] { "<br>" }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string ingredientLine in ingredientLines)
            {
                string ingredientName = ingredientLine;
                Fraction incredientAmountFraction = Fraction.Zero;
                double incredientWeight = 1;
                string[] ingredientParsed = null;

                string measureUnit = GetMeasureUnit(ingredientLine);

                if (measureUnit != null)
                {
                    ingredientParsed = ingredientLine.Split(new string[] { measureUnit }, StringSplitOptions.RemoveEmptyEntries);
                }
                else
                {
                    ingredientParsed = ingredientLine.Split(null as string[], 2, StringSplitOptions.RemoveEmptyEntries);
                }

                try
                {
                    if (ingredientParsed.Length == 1)
                    {
                        incredientAmountFraction = new Fraction(1);
                        ingredientName = ingredientParsed[0].Trim(' ', '-');
                    }
                    else
                    {
                        string incredientAmount = ingredientParsed[0]
                            .Trim(' ', '-')
                            .Replace("חצי", "1/2").Replace("½", "1/2")
                            .Replace("שליש", "1/3")
                            .Replace("רבע", "1/4");
                        incredientAmountFraction = new Fraction(incredientAmount);
                        ingredientName = ingredientParsed[1].Trim(' ', '-');
                        if (measureUnit != null)
                        {
                            incredientWeight = incredientAmountFraction.ToDouble() * IncredientAmount.MEASURE_UNITS[measureUnit];
                        }
                    }
                }
                catch (Exception e) 
                { 
                    log.WarnFormat("Failed to parse ingredient: {0} {1}", ingredientLine, e);
                }

                ProductBasicData product = FindProductByName(ingredientName);
                string productId = null, productName = null;
                NutritionFacts nutFacts = new NutritionFacts();
                if (product != null)
                {
                    productId = product.ProductId;
                    productName = product.ProductName;
                    if (product.ExtendedData != null && product.ExtendedData.NutritionTable != null)
                    {
                        nutFacts = new NutritionFacts(product.ExtendedData.NutritionTable);
                    }
                }
                Ingredient ingredient = new Ingredient()
                {
                    Name = ingredientName,
                    ProductId = productId,
                    ProductName = productName,
                    NutritionFacts = nutFacts,
                    Amount = new IncredientAmount()
                    {
                        MeasureUnit = measureUnit,
                        Amount = incredientAmountFraction,
                        Weight = incredientWeight
                    }
                };
                ingredients.Add(ingredient);
            }

            return ingredients;
        }