【问题标题】:Prime number checker unbelievably slow质数检查器速度慢得令人难以置信
【发布时间】:2011-02-13 11:17:13
【问题描述】:

我有这段代码可以检查给定的数字是否是素数:

If x Mod 2 = 0 Then
    Return False
End If
For i = 3 To x / 2 + 1 Step 2
    If x Mod i = 0 Then
        Return False
    End If
Next
Return True

我只将它用于数字1E7 <= x <= 2E7。但是,它非常慢 - 我几乎无法每秒检查 300 个数字,因此检查所有 x 需要超过 23 天...

有人可以提供一些改进提示或说出我可能会以这种方式多余地做些什么吗?

【问题讨论】:

  • 一开始,您只需要测试到sqrt(x),而不是x/2+1
  • 会更快吗?我猜sqrt(x) 需要更多时间来计算。
  • i 只需要一直到sqrt(x) (注意你只需要计算一次平方根,而不是循环的每次迭代,这样会更快),而不是x / 2 .这应该可以让您更快地测试该范围,但更快的是 Eratosthenes 的筛子。
  • 第一行有错误 - 你写的是i而不是x
  • 刚刚编辑过 - 对不起。

标签: vb.net algorithm primes


【解决方案1】:

这是检查素数的通用算法。 如果要批量检查素数,请使用算法http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

【讨论】:

    【解决方案2】:

    查找术语“埃拉托色尼筛”。这是一个两千年前的算法,比你的要好得多。它经常在学校教授。

    【讨论】:

      【解决方案3】:

      你绝对应该改变你的算法!您可以尝试Sieve of Eratosthenes 或更高级的Fermat primality test。请注意,您的代码会更复杂,因为您需要实现模块化算术。查看 here 以获取一些更高级的数学方法列表。

      【讨论】:

        【解决方案4】:

        你也可以找AKS primality test.
        这是检查素数的好算法。

        【讨论】:

          【解决方案5】:

          由于x/2 + 1 在整个循环操作中都是一个常量,因此请将其保存在For 循环之前的单独变量中。因此,每次循环时都保存 除法和加法 操作。虽然这可能会略微提高性能。

          【讨论】:

          • 我认为编译器应该优化这种情况
          • 编译器也应该这样做。我不知道。谢谢。
          【解决方案6】:

          使用Sieve of Eratosthenes 创建一个Set,其中包含所有质数,直到您需要检查的最大数。设置Set 需要一些时间,但随后检查其中是否存在数字会非常快。

          【讨论】:

            【解决方案7】:

            如果您有多核 cpu,则在一些块中分割范围,并在两个或更多线程中进行检查。或使用Parallel.For

            【讨论】:

            • 感谢您的建议,但我似乎使用了一种非常低效的算法 - 所以我不会使用我的。
            • 在 VB 中进行并行处理之前,我会将语言更改为更快的语言。
            【解决方案8】:

            要检查数字是否为素数,您只需检查它是否不能被小于它的素数除。

            请检查以下sn-p:

             Sub Main()
            
                    Dim primes As New List(Of Integer)
                    primes.Add(1)
            
                    For x As Integer = 1 To 1000
                        If IsPrime(x, primes) Then
                            primes.Add(x)
                            Console.WriteLine(x)
                        End If
                    Next
            
                End Sub
            
                Private Function IsPrime(x As Integer, primes As IEnumerable(Of Integer)) As Boolean
                    For Each prime In primes
                        If prime <> 1 AndAlso prime <> x Then
                            If x Mod prime = 0 Then
                                Return False
                            End If
                        End If
                    Next
                    Return True
                End Function
            

            【讨论】:

            • 非常感谢,这将节省大量时间,主要是因为素数只需要计算一次。但是,我看到存在另一种更快的算法。
            • 只有不大于sqrt(x) 的素数应该被检查。编写的代码仍然很慢 - 二次,而不是 ~&lt; k^1.5,因为产生了 k 素数。操作码只有~ k^2 * log(k)log 的加速大约是 15 倍(23 天 => 1.5 天),但 sqrt 大约是 800 倍(=> 3 分钟)。
            【解决方案9】:

            它很慢,因为您使用的是 x/2。我稍微修改了你的代码。 (我不知道VB的语法,也许你必须改变我的语法。)

            If x < 2 Then
                Return False
            IF x == 2 Then
                Return True
            If x Mod 2 = 0 Then
                Return False
            End If
            For i = 3 To (i*i)<=x Step 2
                If x Mod i = 0 Then
                    Return False
                End If
            Next
            Return True
            

            【讨论】:

              猜你喜欢
              • 2019-06-22
              • 2016-12-05
              • 2016-12-10
              • 2023-03-13
              • 1970-01-01
              • 2013-11-21
              • 2014-12-28
              • 2013-01-06
              • 1970-01-01
              相关资源
              最近更新 更多