首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算Collatz猜想

计算Collatz猜想
EN

Code Review用户
提问于 2016-06-24 17:17:58
回答 3查看 1.1K关注 0票数 2

今天我读到了关于Collatz猜想的东西,我想试着写一个计算所有数字的程序。如果你知道如何缩短代码,请告诉我。

代码语言:javascript
复制
List<string> liste = new List<string>();
long num = 1;
        long z = num;

        while (num != 100000)
        {
            while (z != 1)
            {
                if (z % 2 == 0)
                {
                    z = z / 2;
                }
                else
                {
                    z = (z * 3) + 1;
                }
            }
            liste.Add(num + ": " + z);
            Console.WriteLine(num+": "+z);
            finalnumber = z;
            num++;
        }

            string path = @"N:\Desktop\test.txt";
            File.Delete(path);
            for (int i = 0; i < liste.Count; i++)
            {
                string appendText = ""+liste[i]+"" + Environment.NewLine;
                File.AppendAllText(path, appendText);
            }
EN

回答 3

Code Review用户

发布于 2016-06-24 17:44:33

每次调用File.AppendAllText时,都会创建一个新的文件流,然后关闭它。因此,您不应该通过调用File.AppendAllText n次将结果写入文件。只需使用string.Join

代码语言:javascript
复制
var content = string.Join(Environment.NewLine, list);
File.WriteAllText(content);

您的代码似乎不能正常工作,因为如果到达z == 1 (这是作为初始状态给出的),则不再输入内部while循环。我想在外层while循环的末尾缺少一个z = num;

在非常不可能的情况下,如果您找到一个开始数,而collatz猜想没有以1结束,那么您的程序将处于一个无穷无尽的循环中,您将永远找不出它是哪个数字;)。

票数 1
EN

Code Review用户

发布于 2016-06-27 04:50:47

您的代码同时执行所有操作。它计算数字,打印它们,甚至将它们写入文件。你可以更好地专注于每一项任务,如果你单独做的话,让我们开始.

首先,您想要计算数字,因此为它编写一个函数:

代码语言:javascript
复制
static IEnumerable<int> CalcCollatzConjecture(int z)
{
    var zQueue = new Queue<int>(3);
    var finalSequence = new[] { 4, 2, 1 };
    while(!zQueue.SequenceEqual(finalSequence))
    {
        if (z % 2 == 0)
        {
            z = z / 2;
        }
        else
        {
            z = (3 * z) + 1;
        }
        zQueue.Enqueue(z);
        if (zQueue.Count > finalSequence.Length) { zQueue.Dequeue(); }
        yield return z;
    }
}

当每个序列以[4, 2, 1]结尾时,我们可以将其作为终止符添加,以节省一些时间,而不是一次又一次地计算它。我选择了一个队列来存储最后三个zs。

当你有你的号码..。

代码语言:javascript
复制
var collatzConjecture = CalcCollatzConjecture(1000000).ToList();

你可以用他们做任何你想做的事。您可以打印它们(带有函数):

代码语言:javascript
复制
static void PrintCollatzConjecture(IEnumerable<int> collatzConjecture)
{
    foreach (var z in collatzConjecture)
    {
        Console.WriteLine(z);
    }
}

或者您可以将它们保存在@JanDotNet显示的文件中(也为它编写一个函数)。

票数 1
EN

Code Review用户

发布于 2016-06-27 14:02:10

如果你知道如何缩短代码,请告诉我。..。长num = 1;.同时(数字= 100000) {.num++;}

由于num的作用域是循环,所以不仅可以缩短它,而且可以提高for (long num = 1; num < 100000; num++)的可读性。

while (z != 1) { if (z % 2 == 0) { z = z / 2; } else { z = (z \* 3) + 1; } }

这可以缩短,并可能使更快使用一个基本的按位技巧。x & -x选择x的最小集位,因此

代码语言:javascript
复制
        while (z != 4)
        {
            z = 3 * z / (z & -z) + 1;
        }

做几乎相同的事情:唯一的区别是它在结束时做了一个额外的z * 3 + 1,从而改变了循环条件。

注意:在您的原始代码中和到目前为止所有建议的更改中都可能出现整数溢出: Collatz链中的中间值可能会变得非常大。理想情况下,代码应该检查这一点。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/132964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档