【问题标题】:How can I solve the Collatz conjecture algorithm in C#?如何解决 C# 中的 Collat​​z 猜想算法?
【发布时间】:2011-06-23 05:57:32
【问题描述】:

我能够在大约 5 分钟内使用 Java 解决 Collat​​z 猜想算法(不,我没有试图证明它)。

现在我正在学习 C# 来制作 Web 应用程序,但我在做同样的事情时遇到了麻烦。 我只是想让用户输入一个数字,点击一个按钮,然后将输出打印到一个文本框。

这是我正在使用的按钮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
}

这里是 Collat​​z 方法:

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;
}

编辑 当我使用 VS.net 调试器并输入 2 之类的数字时,我得到 NO 输出和 NO 错误。我只能永远等待。如果它是一个无限循环,我最终会得到一个错误,对吧?

不,这不是家庭作业问题(虽然是 2 年前我在 JAVA 中做的 :)。)我正在独立学习 C#。

【问题讨论】:

  • 您忘记提及您当前的代码到底出了什么问题。你得到一个运行时异常吗?编译器错误?该错误消息的文本是什么?
  • 这听起来像是我的家庭作业,是吗?如果是这样,请相应地标记。 =)
  • 使用更重要的变量名将有助于跟踪您正在尝试执行的操作。
  • 在为大值设置字符串后,if (x==1) 中缺少一个中断

标签: c# .net algorithm collatz


【解决方案1】:
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 类型,因为 Collat​​z 使用自然数。以下是为您的代码添加更多 .NET-ty 的快速重构:

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;
}

【讨论】:

    【解决方案2】:

    你有一个无限循环。试试这个:

    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. 很多时候你不能依赖== 来处理双精度值。在这种情况下它似乎有效,但是当您获得精度较低的更高数字时,它可能不起作用。既然所有的数字都将是 int 的,不妨使用那些。

    【讨论】:

      【解决方案3】:
      if (x == 1)
      {
          y = y+" "+ x.ToString();
          y = y + " largest number was " + large;
      }
      

      这里的这部分(奇数x)是多余的。因为如果 x 为 1,它将永远不会进入 while 循环。您的代码似乎合乎逻辑。也许尝试使用整数。

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

      偶数 x 部分再次出现冗余代码。您如何期望 x 除以 2 后大于 large?只需在 3n+1 部分检查即可。

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

      你可以忽略这部分,让 while 循环处理这个检查。

      【讨论】:

        【解决方案4】:

        View Equation:

        • 如果是偶数:n/2

        • 如果是奇数:3n+1

        第一步:

        添加一个名为 Collazt 的方法,该方法返回 List&lt;?&gt; 类的 int 类型对象的集合

        public static List<int> Collazt(int n) {
                    List<int> data = new List<int>();
                    data.Add(n);
        
                    int resul = 0;
        
                    while (true) {
        
                        if (n == 1) {
                            break;
                        }
                        if ((n % 2) == 0)
                        {
                            resul = n / 2;
                            n = resul;
        
                        }
                        else {
                            resul = (n * 3) + 1;                    
                            n = resul;
                        }
        
                        data.Add(n);                
                    }
        
                    return data;
                }
        

        第二步:

        我们在主类中调用该方法。

        static void Main(string[] args)
                {
                    
                    Console.Write("N: ");
                    int r = int.Parse(Console.ReadLine());
                    List<int> result = Collazt(r);
                    Console.WriteLine("Lista:");
                    Console.WriteLine("[");
                    for (int i= 0; i<result.Count; i++) {
                        Console.Write(result[i]+"\n");
                    }
                    Console.WriteLine("]");
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-06-15
          • 2019-03-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-08
          相关资源
          最近更新 更多