【问题标题】:C# Prime Numbers with LINQ使用 LINQ 的 C# 素数
【发布时间】:2015-10-20 16:53:45
【问题描述】:

这些天我对 LINQ 很感兴趣。我正在尝试获取质数。我实际上做得很好,但我的代码没有显示低于 Sqrt(n) 的素数。

static void Main(string[] args)
    {

        Func<int, int, IEnumerable<int>> EnumerableRange =
            (startPoint, endPoint) =>
                Enumerable.Range(Math.Min(startPoint, endPoint), Math.Abs(startPoint - endPoint) + 1);

        Func<int, int, bool> isFullyDivided =
            (value, divisor) =>
                (value % divisor).Equals(0);

        int sp = 2,
            ep = 100;

        var query =
            EnumerableRange(sp, ep)
            .Where(value =>
                EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(ep)))
                .Any(divisor =>
                    isFullyDivided(value, divisor))
                    );

        var primeNumbers =
            EnumerableRange(sp, ep)
            .Except(query);

        foreach (var item in primeNumbers)
        {
            Console
                .WriteLine(item);
        }

        Console
            .Read();

    }

目前,此代码错误地忽略了小于sqrt(n) 的素数。该代码应该得到 2 到 100 之间的素数。相反,它只打印 11 及以上的素数。缺少素数 2, 3, 5, 7

【问题讨论】:

  • 您能否更具体地说明您的代码是如何不工作的?
  • 以下代码表示素数 11 及以上。 11 以下,即 2、3、5、7 缺失。

标签: c# linq lambda primes


【解决方案1】:

您的除数约束不正确 - 您正在查看 2 和 Sqrt(ep) (10) 之间的除数,而您只需要检查 2 和 Sqrt(value) 之间的除数:

    var query =
        EnumerableRange(sp, ep)
        .Where(value =>                                      V----------
            EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(value)))
            .Any(divisor =>
                isFullyDivided(value, divisor))
                );

这就是为什么你的素数从 11 开始,因为你的除数上升到 10,这将包括值本身。 @ryanyuyu 的回答也以不同的方式解决了同样的问题。您的代码仍将检查不必要的除数。

【讨论】:

  • @ryanyuyu 的回答是正确的。我错过了那个条件。 !value.Equals(除数)
  • 如果您更改除数选择,则不需要该条件。
  • 是的 - 你仍然需要使用你的方法的条件,但我仍然认为你可以减少除数的范围。一旦你越过Sqrt(value),你就在做不必要的比较@大多数素数生成器显式地添加 2 和 3,然后从 2 循环到Floor(Sqrt(n))
  • 谢谢你,Sqrt(value) 更快。
  • 这是一个很好的改进,可以减少所需比较的次数。
【解决方案2】:

你有一个逻辑问题。一切都可以平均分配,所以你应该检查value != divisor。否则你会错误地排除自相除的数字(例如5 % 5 == 0)。

var query =
    EnumerableRange(sp, ep)
    .Where(value =>
        EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(ep)))
        .Any(divisor =>
             value != divisor &&  //This is the logic you are missing
             isFullyDivided(value, divisor))
            );

【讨论】:

  • 谢谢。真的谢谢。我像几个小时一样思考“我错过了什么?该死的。”真的很感激。
【解决方案3】:

最佳解决方案:

            var query =
            EnumerableRange(sp, ep)
            .Where(value =>
                EnumerableRange(2, (int)Math.Ceiling(Math.Sqrt(value)))
                .Any(divisor =>
                    !value.Equals(divisor) &&
                    isFullyDivided(value, divisor))
                    );

Math.Floor 是错误的。正确的是 Math.Ceiling。

【讨论】:

    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2012-06-23
    相关资源
    最近更新 更多