【问题标题】:Generate Prime Numbers via Eratosthene's Sieve C#通过 Eratosthenes Sieve C# 生成素数
【发布时间】:2016-12-14 00:27:18
【问题描述】:

我正在尝试解决 Project Euler 的问题 3,发现 here. 我想通过使用 Eratosthene 的筛子生成素数列表来解决它(发现 here. 我还没有完成这个问题,但我遇到了一个小问题...

以下是我为此编写的代码。但是,当我运行此代码时,它会停止我的计算机,并在停止之前输出 2。它显然正在运行,但它似乎并没有做对。在它输出列表之前,它应该让我知道(只是检查挂断是否在输出之前)它已完成分配列表...

如果您不确定发生了什么,您能否给我一些指导,以便深入研究代码并调试其不同的行?我在不同的区域尝试过 Console.WriteLine,但它似乎没有响应代码。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    static void Main(string[] args)
    {
        long maxNum = 100;
        double maxSqrt = Math.Floor(Math.Sqrt(maxNum));
        long basePrime;
        // Make a list from 2 to maxNum
        List<long> numberList = new List<long>();
        List<long> sievedList = new List<long>();
        for (long i = 2; i <= maxNum; i++) numberList.Add(i);
        // Evaluate the first number of the list, if it is < maxSqrt skip it, create a list of multiples and Except them from numberList, else, numberList is completely Prime Factors

        foreach (long number in numberList.Skip(1))
        {
            basePrime = numberList[0];
            Console.WriteLine(basePrime);
            while (number < maxSqrt)
                {
                    if (number % basePrime == 0)
                    {
                        sievedList.Add(number);
                    }
                    numberList = numberList.Except(sievedList).ToList();
                    sievedList.Clear();
                }
        }
    Console.WriteLine("Finished Allocating Primes");   
    numberList.ForEach(Console.WriteLine);
    }
}

【问题讨论】:

  • maxSqrt 不应更改,除非 maxNum 更改。我的印象是一个数的平方根是最高的,它的因数可以而且仍然可能是素数。
  • 你现在真的应该开始学习使用调试器了。它会在您的while 循环中发现错误,而花费的时间比您在此处创建问题所花费的时间要少得多。单步调试代码也可以教给您很多关于编写代码的更好方法。你永远不会改变number,所以它会一直保持&lt; maxSqrt,所以你的循环永远不会退出。它被称为无限循环。
  • 那么,while 循环实际上不会改变它的值,因为直到 number 大于 maxSqrt 才会改变?
  • 你在 while 循环中什么也不做来改变数字。你希望它自己改变吗?如果数字 从不改变,并且开始时小于 maxSqrt,那么它将保持 从不退出。如果数字开始较低且永不更改,则数字可以从不 > maxSqrt。想一想:number = 3,maxSqrt = 10。如果 number 保持为 3,它怎么会大于 10 才能退出循环?或者更好的是 - 在调试器中逐步执行代码。只需大约三遍循环观看number 即可看到问题。
  • 你在素数/平方数上搞错了:34=2*17。平方(34)

标签: c# primes


【解决方案1】:

对于您的直接问题,请将while 更改为if

但是您的代码也有其他问题。

  • 您的numberedList 只是一个从2 到maxNum 的整数列表,您正在使用for 循环对其进行填充。然后你遍历列表。只需使用 for 循环中的计数器即可。为了记录哪些数字是素数,BitArray(Int32, Boolean) 效果很好。
  • 这也允许摆脱昂贵的 LINQ 扩展。当您找到一个非质数时,只需更改它在 BitArray 中的索引。当您找到一个素数时,将其添加到列表中;

【讨论】:

  • 是的,以前的 cmets 指出了这一点!我一直在修补它,但就像你说的,它有严重的问题。我将不得不阅读 BitArray,但这看起来像一个游戏规则改变者。谢谢!
【解决方案2】:

灵感来源: Laziness in Python - Computerphile 我将其翻译成 C#:

using System;
using System.Collections.Generic;
using System.Linq;

namespace GenertatorTest
{
    class Program
    {
        /// <summary>
        /// Natural Numbers Genarator
        /// </summary>
        /// <param name="first">first number in the sequence</param>
        /// <returns>the sequence: first, first + 1, first + 2, ... ∞</returns>
        static IEnumerable<int> natural(int begin)
        {
            yield return begin;
            foreach (var item in natural(begin + 1))
            {
                yield return item;
            }
        }

        /// <summary>
        /// Primary Numbers Genarator
        /// </summary>
        /// <param name="nums">natural numbers sequence which we want to apply  Eratosthene's Sieve on</param>
        /// <returns>infinite primary numbers sequence</returns>
        static IEnumerable<int> primes(IEnumerable<int> nums)
        {
            int p = nums.ElementAt(0);
            yield return p;
            foreach (var item in primes(nums.Where(x => x % p != 0)))
            {
                yield return item;
            }
        }

        static void Main(string[] args)
        {
            foreach (var item in primes(natural(2)))
            {
                Console.WriteLine(item);
                //it is infinite sequence
                //so you cant just run through. 
                Console.ReadKey();
            }
        }
    }
}

其实这段代码比你想象的要优雅。我们这里唯一缺少的语法糖是yield from,C# 似乎不支持它。

【讨论】:

    猜你喜欢
    • 2016-04-05
    • 1970-01-01
    • 2018-08-10
    • 2012-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多