Как упростить дроби?

Как упростить дробь в С#? Например, учитывая 1 11/6, мне нужно упростить его до 2 5/6.


person hi tech id    schedule 13.03.2011    source источник
comment
Что, если бы ввод был 1 10/6, вы бы хотели 2 4/6 или 2 2/3?   -  person sepp2k    schedule 13.03.2011
comment
@ sepp2k Поскольку 2 2/3 - это упрощенная форма, я предполагаю, что он этого хочет.   -  person CathalMF    schedule 01.04.2016


Ответы (4)


Если все, что вам нужно, это превратить вашу дробь в смешанное число, дробная часть которого является правильной дробью, как предполагалось в предыдущих ответах, вам нужно всего лишь добавить numerator / denominator ко всей части числа и установить числитель в numerator % denominator. Использование циклов для этого совершенно необязательно.

Однако термин «упростить» обычно относится к сокращению дроби до ее наименьшего значения. Ваш пример не дает понять, хотите ли вы этого, поскольку пример в любом случае находится в самых низких терминах.

Вот класс C#, который нормализует смешанное число таким образом, что каждое число имеет ровно одно представление: дробная часть всегда правильная и всегда в наименьшем выражении, знаменатель всегда положительный, а знак целой части всегда такой же, как у целой части. знак числителя.

using System;

public class MixedNumber {
    public MixedNumber(int wholePart, int num, int denom)
    {  
        WholePart = wholePart;
        Numerator = num;
        Denominator = denom;
        Normalize();
    }

    public int WholePart { get; private set; }
    public int Numerator { get; private set; }
    public int Denominator { get; private set; }

    private int GCD(int a, int b)
    {  
        while(b != 0)
        {  
            int t = b;
            b = a % b;
            a = t;
        }
        return a;
    }

    private void Reduce(int x) {
        Numerator /= x;
        Denominator /= x;
    }

    private void Normalize() {
        // Add the whole part to the fraction so that we don't have to check its sign later
        Numerator += WholePart * Denominator;

        // Reduce the fraction to be in lowest terms
        Reduce(GCD(Numerator, Denominator));

        // Make it so that the denominator is always positive
        Reduce(Math.Sign(Denominator));

        // Turn num/denom into a proper fraction and add to wholePart appropriately
        WholePart = Numerator / Denominator;
        Numerator %= Denominator;
    }

    override public String ToString() {
        return String.Format("{0} {1}/{2}", WholePart, Numerator, Denominator);
    }
}

Пример использования:

csharp> new MixedNumber(1,11,6);     
2 5/6
csharp> new MixedNumber(1,10,6);   
2 2/3
csharp> new MixedNumber(-2,10,6);  
0 -1/3
csharp> new MixedNumber(-1,-10,6); 
-2 -2/3
person sepp2k    schedule 13.03.2011

int unit = 1;
int numerator = 11;
int denominator = 6;

while(numerator >= denominator)
{
    numerator -= denominator;
    if(unit < 0)
        unit--;
    else
        unit++;
}

Затем делайте с переменными все, что хотите.

Обратите внимание, что это не особенно общее... в частности, я сомневаюсь, что это будет хорошо работать с отрицательными числами (изменить: сейчас может быть лучше)

person Owen    schedule 13.03.2011
comment
Похоже, вы должны сделать numerator >= denominator. Что позволило бы 6/6 == 1 - person jb.; 13.03.2011
comment
Я думаю, что это работает, но я также думаю, что бодрствовать в 5 утра из-за переполнения стека — не очень хорошая идея, поэтому ваш пробег может отличаться. - person Owen; 13.03.2011
comment
хаха, так верно. Это ближе, но подумайте, если у вас есть -11/6, он никогда не войдет в ваш цикл. -11 не >= 6 - person jb.; 13.03.2011

int num = 11;
int denom = 6;
int unit = 1;
while (num >= denom)
{
  num -= denom;
  unit++;
}

Извините, я не совсем понял эту часть об отслеживании значений единиц.

person Jim    schedule 13.03.2011
comment
это как бы говорит о том, что 11/6 == 5/6. вы отсекаете целую часть числа. - person jb.; 13.03.2011
comment
Это должно отслеживать единицу... переменная единицы вместе с num и denom, которая увеличивается в цикле while, добьется цели. - person Owen; 13.03.2011
comment
Цикл всегда был предназначен, я просто не понимал, что они хотят отслеживать значение единицы. - person Jim; 13.03.2011
comment
Есть много отрицательных голосов, но не так много объяснений этому. Комментарии здесь не просто так, ребята! - person Owen; 13.03.2011
comment
Присвоение его длинному бессмысленно и приведет к неправильному результату. Вы могли бы также сохранить его в дробной форме. Счетчик вызовов, что это такое: единицы (или часть целого числа). - person Robert Harvey; 13.03.2011
comment
+1 Роберту. как бы то ни было, весь этот код можно было бы выполнить, просто сохранив num/denom в длинном - person jb.; 13.03.2011
comment
Хорошо, я понимаю вашу точку зрения, я просто хотел бы, чтобы точность здесь была хорошей. - person Jim; 13.03.2011
comment
@Jim: int все равно даст неверный результат. Подумайте об этом: вы пытаетесь сохранить 5/6 в целочисленной переменной. Если он скомпилируется и запустится (что, я думаю, не произойдет, не без приведения), fract будет содержать два, а не ожидаемое значение 2+5/6. - person Robert Harvey; 13.03.2011
comment
Так-то лучше. Я сделал несколько дополнительных мелких исправлений и удалил свой отрицательный голос. Вы можете увидеть изменения здесь: stackoverflow.com/posts/5287530/revisions. - person Robert Harvey; 13.03.2011
comment
а) Это не сработает, если одно из чисел отрицательное. б) Использование цикла для этого слишком сложно, все, что вам нужно, это целочисленное деление и модуль. c) Я не уверен, что правильная дробь - это все, чего хочет ОП - это не то, что обычно означает упрощение дроби. - person sepp2k; 13.03.2011

чтобы упростить дробь 6/11, вы бы увидели, сможете ли вы выстроить их в линию на одно и то же число больше 1 и разделить.

So

  • 2,4,6,8,10,12 no
  • 1,3,6,9,12 no
  • 4,8 no
  • 5,10 no
  • 6,12 no
  • 7 no
  • 8 no
  • 9 no.

Нет будет ответом для всех, так что это уже в самом простом. Больше ничего не нужно делать.

person mystery    schedule 08.11.2013