Сложение и вычитание вульгарных дробей

Я пытаюсь сложить две вульгарные дроби вместе, найдя наименьший общий знаменатель и затем сложив. Однако мой код ведет себя не так, как ожидалось, и выводит два очень высоких отрицательных числа. Когда я изменяю вторую дробь на 3/15, она выводит 0/0.

Вот мой основной программный код:

class Program
{
    static void Main(string[] args)
    {
        Fraction n = new Fraction(2, 4);
        Fraction z = new Fraction(3, 12);

        Fraction sum = n.Add(z, n);
        int num = sum.Numerator;
        int den = sum.Denominator;

        Console.WriteLine("{0}/{1}", num, den);
        Console.ReadKey(true);
    }
}

Вот мой код Fraction класса:

internal class Fraction
{
    public Fraction(int numerator, int denominator)
    {
        Numerator = numerator;
        Denominator = denominator;
    }

    public int Numerator { get; private set; }

    public int Denominator { get; private set; }

    public Fraction Add(Fraction fraction2, Fraction fraction8)
    {
        int lcd = GetLCD(fraction8, fraction2);

        int x = lcd/fraction8.Denominator;
        int n = lcd/fraction2.Denominator;
        int f2num = fraction2.Numerator*n;
        int f8num = fraction8.Numerator*x;

        int t = fraction2.Numerator;

        Fraction Fraction3 = new Fraction(f2num+f8num,lcd);

        return Fraction3;
    }



    public int GetLCD(Fraction b, Fraction c)
    {
        int i = b.Denominator;
        int j = c.Denominator;

        while (true)
        {

            if (i == j)
            {
                return i;
            }
            j = j + j;
            i = i + i;
        }
    }
}

person user2723261    schedule 25.09.2013    source источник
comment
полезные имена переменных были бы хорошим началом   -  person Jonesopolis    schedule 25.09.2013
comment
Хорошо, что OP включил сюда все операторы using. Если серьезно, вам нужно немного сузить проблему. Похоже, что вы вообще не приложили никаких усилий, чтобы отладить это. Кроме того, имена ваших переменных ужасны.   -  person tnw    schedule 25.09.2013
comment
GetLCD не делает то, что вы думаете.   -  person Dave Zych    schedule 25.09.2013
comment
Как и выше, GetLCD возвращает -2147483648 на моем компьютере. Кроме того, я не думаю, что здесь лучше всего на время выглядеть.   -  person OMGtechy    schedule 25.09.2013
comment
@DaveZych, спасибо, что ответил на мой вопрос. Не могли бы вы уточнить еще немного, пожалуйста?   -  person user2723261    schedule 25.09.2013
comment
@ user2723261 Посмотрите на ответ Кришны для правильной реализации. В качестве быстрого примера, если вы передадите 2 и 4 в свой метод GetLCD, первая итерация проверяет 2 == 4, вторая проверяет 4 == 8, третья проверяет 8 == 16 и т.д. и т.д. и т. Д. Они никогда не будут равны. Я предполагаю, что единственная причина, по которой что-то было возвращено, - это переполнение или что-то в этом роде.   -  person Dave Zych    schedule 26.09.2013


Ответы (2)


Не имело смысла иметь GetLCD, Add & Subtract методов в классе. Итак, я вынес его из класса и сделал для них статические методы.

Ваша GetLCD функция неправильно отображает ЖК-дисплей. Это даст вам требуемый результат (я не беспокоился о том, чтобы заставить работать метод Subtract, вы можете следовать приведенному ниже коду и заставить его работать самостоятельно)

PS: Я не менял все ваши имена переменных, и я бы порекомендовал вам сделать их как можно более значимыми. n, z, x, y, b, c - плохие имена переменных

    static void Main(string[] args)
    {
        Fraction n = new Fraction(2, 4);
        Fraction z = new Fraction(3, 12);

        Fraction sum = Add(z, n);
        int x = sum.Numerator;
        int y = sum.Denominator;

        Console.WriteLine("{0}/{1}", x, y);
        Console.ReadKey(true);
    }

    public static Fraction Add(Fraction fraction2, Fraction fraction8)
    {

        int lcd = GetLCD(fraction8, fraction2);
        int multiplier = 0;
        if (fraction2.Denominator < lcd)
        {
            multiplier = lcd / fraction2.Denominator;
            fraction2.Numerator = multiplier * (fraction2.Numerator);
            fraction2.Denominator = multiplier * (fraction2.Denominator);
        }
        else
        {
            multiplier = lcd / fraction8.Denominator;
            fraction8.Numerator = multiplier * (fraction8.Numerator);
            fraction8.Denominator = multiplier * (fraction8.Denominator);
        }

        Fraction Fraction3 = new Fraction(fraction2.Numerator + fraction8.Numerator, lcd);

        return Fraction3;
    }

    public static int GetLCD(Fraction b, Fraction c)
    {
        int i = b.Denominator;
        int j = c.Denominator;

        int greater = 0;
        int lesser = 0;

        if (i > j)
        {
            greater = i; lesser = j;
        }
        else if (i < j)
        {
            greater = j; lesser = i;
        }
        else
        {
            return i;
        }
        for (int iterator = 1; iterator <= lesser; iterator++)
        {
            if ((greater * iterator) % lesser == 0)
            {
                return iterator * greater;
            }
        }
        return 0;
    }

    internal class Fraction
    {
        public Fraction(int numerator, int denominator)
        {
            Numerator = numerator;
            Denominator = denominator;
        }
        public int Numerator { get; set; }
        public int Denominator { get; set; }
    }
person Venkata Krishna    schedule 25.09.2013

Лично я думаю, что ваша первая ошибка - это попытка вычислить наименьший общий знаменатель, а не просто найти простейший общий знаменатель. Поиск ЖК-дисплея - отличная стратегия для людей, решающих эту задачу на бумаге из-за распознавания образов: мы можем быстро распознать ЖК-дисплеи; но вычисление ЖК-дисплея и последующее преобразование в него дробей - это значительно больше шагов для компьютера, который должен выполнять каждый шаг каждый раз (и не может распознавать шаблоны). Кроме того, если вы сложите две дроби после преобразования их на ЖК-дисплей, это даже не гарантирует уменьшения результата. Я предполагаю, что требуется сокращенный результат, как обычно ожидается с дробной арифметикой. И поскольку это кажется полезным, я поместил сокращение непосредственно в код конструктора:

internal class Fraction
{
public Fraction(int numerator, int denominator, bool reduce = false)
{
    if (!reduce)
    {
        Numerator = numerator;
        Denominator = denominator;
    }
    else
    {
        var GCD = GreatestCommonDivisor(numerator, denominator);
        Numerator = numerator / GCD;
        Denominator = denominator / GCD;
    }
}

public int Numerator { get; private set; }

public int Denominator { get; private set; }    

public static Fraction Add(Fraction first, Fraction second)
{
    return Combine(first, second, false);
}

public static Fraction Subtract(Fraction first, Fraction second)
{
    return Combine(first, second, true);
}

private static Fraction Combine(Fraction first, Fraction second, bool isSubtract)
{
    var newDenominator = first.Denominator * second.Denominator;
    var newFirst = first.Numerator * second.Denominator;
    var newSecond = first.Denominator * second.Denominator;

    if (isSubtract)
    {
        newSecond = newSecond * -1;
    }

    return new Fraction(newFirst + newSecond, newDenominator, true);
}

private static int GreatestCommonDivisor(int a, int b) 
{
    return b == 0 ? a : GreatestCommonDivisor(b, a % b);
}

}

Изменить: украл код наибольшего общего делителя из этого ответа

person User    schedule 25.09.2013