Как я могу решить алгоритм гипотезы Коллатца в C #? - PullRequest
0 голосов
/ 08 февраля 2011

Мне удалось решить алгоритм гипотезы Коллатца (нет, я не пытался это доказать) примерно за 5 минут с использованием Java.

Теперь, когда я изучаю C # для создания веб-приложений, у меня возникают проблемы с тем же. Я просто хочу, чтобы пользователь ввел число , нажал кнопку и распечатал вывод в текстовое поле.

Вот кнопка Click метод обработчика событий, который я использую:

protected void Button3_Click(object sender, EventArgs e)
{
    string x = TextBox1.Text;   //user entered a number
    string y =collatz(x);       //this function is below and returns a string
    chatbox.Text = y;           //output
}

А вот метод Коллатца:

public static string collatz(string y)
{   
    if (y == null)
        return null;

    double x = double.Parse(y); //x is my "n"
    y = x.ToString(); //output string

    double large = x; //keep track of biggest number

    // the algorithm
    // the redundancies (like x==1.. x!= 1) are part of troubleshooting :/

    while (x > 1)
    {
        if (x % 2 == 0)
        {
            x = x / 2;
            if (x > large)
                large = x;
            if (x != 1)
                y = y+" "+ x.ToString();
            if (x == 1)
            {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
        }

        if (x % 2 != 0)
        {
            if (x == 1)
            {
                y = y+" "+ x.ToString();
                y = y + " largest number was " + large;

            }

            x = (3 * x) + 1;
            if (x > large)
                large = x;
            y = y+" "+ x.ToString();

        }
    }

    return y;
}

EDIT когда я использую отладчик VS.net и ввожу число, подобное 2, я получаю НЕТ вывода и НЕТ ошибки. Я просто жду вечно. Если бы это был бесконечный цикл, я бы в итоге получил ошибку, верно?

и нет, это не проблема домашней работы (хотя это было 2 года назад, когда я делал это в JAVA :).) Я изучаю C # самостоятельно.

Ответы [ 3 ]

2 голосов
/ 08 февраля 2011

У вас был бесконечный цикл.Попробуйте это:

public static string collatz(string y)
{
    if (y == null)
    {
        return null;
    }

    int x = int.Parse(y); //x is my "n"
    var results = new StringBuilder();
    results.Append(x.ToString());
    int largest = x; //keep track of biggest number

    // the algorithm
    // the redundancies (like x==1.. x!= 1) are part of troubleshooting :/
    while (x > 1)
    {
        if (x % 2 == 0)
        {
            x = x / 2;
            if (x > largest)
            {
                largest = x;
            }
            if (x != 1)
            {
                results.Append(" " + x.ToString());
            }
            if (x == 1)
            {
                results.Append(" " + x.ToString());
                results.Append(" largest number was " + largest.ToString());
                return results.ToString();
            }
        }

        if (x % 2 != 0)
        {
            if (x == 1)
            {
                results.Append(" " + x.ToString());
                results.Append(" largest number was " + largest.ToString());
                return results.ToString();
            }
            x = (3 * x) + 1;
            if (x > largest)
            {
                largest = x;
            }
            results.Append(" " + x.ToString());
        }
    }
    return results.ToString();
}

Два примечания:

  1. Когда вы делаете конкатенацию строк в цикле, это хорошая привычка использовать StringBuilder вместоs = s + t.Много, намного меньше памяти.

  2. Часто вы не можете положиться на ==, когда речь идет о двойных значениях.Похоже, что в этом случае работает, но это может не сработать, когда вы достигнете более высоких чисел, где точность меньше.Так как все числа будут в любом случае целыми числами, их также можно использовать.

1 голос
/ 08 февраля 2011
if (x == 1)
{
    y = y+" "+ x.ToString();
    y = y + " largest number was " + large;
}

Эта часть здесь (нечетная х) является избыточной. Если x равен 1, он никогда не войдет в цикл while. Ваш код кажется логичным. Возможно, вместо этого попробуйте использовать целое число.

x = x / 2;
if (x > large)
    large = x;

Снова избыточный код для четной части x. Как вы думаете, х будет больше, чем большой после деления на 2? Просто проверьте это в части 3n + 1.

if (x == 1)
{
    y = y + " " + x.ToString();
    y = y + " largest number was " + large;
}

Вы можете просто пропустить эту часть и позволить циклу while обрабатывать эту проверку.

0 голосов
/ 08 февраля 2011
public static string collatz(string y)
{
    if (y == null)
        return null;
    double x = double.Parse(y);
    y = x.ToString();
    double large = x;
    while (x > 1) {
        if (x % 2 == 0) {
            x = x / 2;      // x reassigned
            if (x > large)
                large = x;
            if (x != 1)
                y = y + " " + x.ToString();
            if (x == 1) {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
        }
        // Infinite loop goes because of that
        if (x % 2 != 0) {  // double check on reassigned variable, use “else” instead
            if (x == 1) {
                y = y + " " + x.ToString();
                y = y + " largest number was " + large;

            }
            x = (3 * x) + 1;
            if (x > large)
                large = x;
            y = y + " " + x.ToString();
        }
    }
    return y;
}

Я попробовал его с фиксированным кодом (используя else), и он отлично работает.

Кроме того, вам не нужен тип double, так как Collatz работает с натуральными числами.Ниже приведен быстрый рефакторинг для добавления дополнительных .NET-типов в ваш код:

public static string collatz(string input)
{
    int current = 0;
    if (string.IsNullOrEmpty(input) || !int.TryParse(input, out current) || current < 1) {
        return "Empty, not a number or less then 1";
    }
    int max = current;
    while (current > 1) {
        if (current % 2 == 0) {
            current = current / 2;          // current reassigned
            if (current > max)
                max = current;
            if (current != 1)
                input = input + " " + current.ToString();
            if (current == 1) {
                input = input + " " + current.ToString();
                input = input + " largest number was " + max;

            }
        } else {
            if (current == 1) {
                input = input + " " + current.ToString();
                input = input + " largest number was " + max;
            }
            current = (3 * current) + 1;
            if (current > max)
                max = current;
            input = input + " " + current.ToString();
        }
    }
    return input;
}
...