【问题标题】:c# program freezes on list of integersc#程序冻结在整数列表上
【发布时间】:2018-09-11 06:02:11
【问题描述】:

当我运行我的程序时,我发现我初始化了一个整数列表并且它冻结了。我知道这是因为 Console.WriteLine();列表初始化后的方法不会出现在控制台上。当我运行它时,唯一的输出是“列表之前”。我错过了什么?我真的希望这不是显而易见和令人尴尬的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Euler._1_50
{
    class Challenge3
    {
        public Challenge3()
        {
            Console.WriteLine("before list");

            long num = 600_851_475_143;
            long high = 0;
            long length = 0;
            List<int> factr = new List<int>();

            Console.WriteLine(IsPrime(num));
            Console.WriteLine("after list");

            for (long i = 2; i <= num / 2; i++)
            {
                if (IsPrime(i) && num / i == 0)
                {
                    num = num / i;
                    factr.Add((int)i);
                    length++;
                }
            }

            for (long i = 0; i <= length; i++)
            {
                if (i > high) high = i;
            }

            Console.WriteLine(high);

        }

        private bool IsPrime(long i)
        {
            bool isPrime = false;

            for (long j = 2; j <= i/2; j++)
            {
                if (i % j == 0) isPrime = false;
                else isPrime = true;
            }
            return isPrime;
        }
    }
}

【问题讨论】:

  • 运行 3000 亿次迭代需要时间。尝试在 (j % 1000) == 0 时在 IsPrime 中添加 Console.Writeline。
  • 你知道,这很有意义。不用说我是编程新手。
  • 尝试计算 终极问题 的答案是 42...需要很长时间的人。

标签: c# list integer initialization factors


【解决方案1】:

挂起的不是List&lt;T&gt; 构造函数。它是 IsPrime600_851_475_143 作为参数调用的。随着循环运行到一半,它是 3000 亿次迭代。这需要时间。

即使您等待它返回,下一个循环也会运行 IsPrime 以处理 2 到相同的 3000 亿之间的所有整数。这将需要更长的时间才能完成。它需要对最内层循环进行超过 90 万亿次迭代!

不是 100% 清楚你想要做什么,但你应该考虑一种不同的算法,因为无论你如何编码,这个算法都会运行得很慢。

【讨论】:

  • 更不用说IsPrime 方法可能还是有问题的(因为isPrime 被任意分配,没有中断条件)。
  • 您可以做一些事情来让IsPrime 更快。正如彼得在他的回答中所说,您可以在sqrt(i) 停下来。您也可以跳过所有偶数,因为如果一个数字不除以 2,它也不会除以任何其他偶数。所以从 3 开始,然后使用 += 2 而不是 ++。另外,当您找到第一个值时,您应该添加break。无需检查其他任何内容。但即便如此,它也会很慢。
【解决方案2】:

IsPrime 将运行至少 3000 亿次迭代,这就是它锁定的原因。

整数的质因数永远不会大于该整数的平方根。

此外,一旦你确定这个数是素数,你就不需要继续检查了。

因此考虑将您的测试循环更改为:

private bool IsPrime(long i)
{
    long upper = (long)Math.Sqrt(i);
    for (long j = 2; j <= upper; j++)
    {
        if (i % j == 0)
           return false;
    }
    return true;
}

最后,关于“high”的最后一段代码表明您打算在更大的代码段中使用它。如果是这种情况,您最好预先计算哪些数字是素数,然后将它们存储在 List 或 HashSet 中以便快速重复使用。

【讨论】:

    【解决方案3】:

    所以我正在做 Project Euler 问题。在我做这件事的前一天,我设法制作了一个涂料素数查找算法,但我懒得把它放到第一篇文章中看到的素数分解问题中。在又一天拒绝查找答案和讨厌生活之后,我终于写出了一个更好的程序。我现在可以在大约半秒内找到答案。可能更清洁,但它完成了我需要它完成的工作。 #满足感

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Euler._1_50
    {
        class Challenge3_1
        {
            List<long> primes = new List<long>();
            List<bool> isPrime = new List<bool>();
            List<int> factors = new List<int>();
    
            long primeNums = 0;
            long bigNum = 600_851_475_143;
            int primeBnds = 1_000_000;
    
            public Challenge3_1()
            {
                genList();
                getPrimes();
                //listPrimes();
                factor();
    
                Console.WriteLine("final");
                listFactors();
            }
    
    
            //not currently being used
            private void genList()
            {
                for (int i = 0; i <= primeBnds; i++)
                {
                    isPrime.Add(true);
                }
            }
    
            private void getPrimes()
            {
                isPrime[0] = false;
                isPrime[1] = false;
    
                for (int i = 2; i <= primeBnds; i++)
                {
                    if (isPrime[i] == true)
                    {
                        for (int j = i, index = 0; index <= primeBnds; index += j)
                        {
                            if (j < index)
                            {
                                isPrime[index] = false;
                            }
                        }
                    }
                }
            }
    
            private void factor()
            {
                long temp = bigNum;
    
                for (int i = 2; i <= primeBnds;)
                {
                    if (isPrime[i] == true && temp % i == 0)
                    {
                        temp = temp / i;
                        factors.Add(i);
                        Console.WriteLine(i);
                    }
    
                    if (temp % i != 0)
                    {
                        i++;
                    }
    
                    //if (factors.Capacity != 0) listFactors();
                }
    
            }
    
            private void listPrimes()
            {
                for (int i = 0; i <= primeBnds; i++)
                {
                    if (isPrime[i] == true)
                    {
                        Console.WriteLine(++primeNums + " " + i);
                    }
                }
            }
    
            private void listFactors()
            {
                for (int i = 0; i < factors.Capacity; i++)
                {
                    Console.Write(factors[i] + " ");
                }
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-12-15
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 2018-09-01
      • 1970-01-01
      相关资源
      最近更新 更多