通过VBA编码写出1到100之间的素数

Write prime numbers between 1 to 100 through VBA coding

我找到了下面的代码,但它不起作用。请在VBA

中分享更合适的写质数的代码
Private Sub cmdPrime_Click()
Dim p, n, i As Integer
p = 1
Print “Prime Numbers are : ”
For n = 1 To 100
For i = 2 To n – 1
If n Mod i = 0 Then
p = 0
Exit For
Else
p = 1
End If

Next
If p = 1 Then
Print n
End If

Next
End Sub

我猜你是从另一种语言翻译过来的?您真的应该指出哪些线路出现故障以及您研究了什么。

“”:智能引号。这是在应用程序之间复制时的典型情况,所以要小心。 visual basic 编辑器中使用的语音标记需要""才能编译。

如果你把 Option Explicit 放在代码的顶部,它会给你很多关于变量声明和拼写的警告。

你只需要 100,所以 Integer 没问题,但是在这种情况下 Integer 没有 Long 的优势,所以使用 Long 更安全如果您将来决定超出 Integer 的容量,那么您就有溢出的风险。如果上限足够高,您还需要考虑 mod

The MOD function returns an error if the divisor (the second argument in the MOD function), multiplied by 134,217,728, is less than or equal to the number being evaluated (the first argument in the MOD function).

Microsoft 建议改写为 =number-(INT(number/divisor)*divisor);我猜你可以用 CLng 替换 INT 以与 Longs 保持一致。

Option Explicit
Private Sub cmdPrime_Click()
    Dim p As Long, n As Long, i As Long, iCounter As Long
    p = 1
    With ActiveSheet
        .Cells(iCounter + 1, 1) = "Prime Numbers are: " 'Debug.Print "Prime Numbers are: "
        For n = 2 To 100 ''< As pointed out 1 is not technically a prime btw so can start at 2
            For i = 2 To n - 1
                If n Mod i = 0 Then              ' If n - (CLng(n / i) * i) = 0 Then
                    p = 0
                    Exit For
                Else
                    p = 1
                End If
            Next
            If p = 1 Then
                iCounter = iCounter + 1
                .Cells(iCounter, 1) = n  'Debug.Print n  
            End If
        Next
    End With
End Sub

为未来的读者保留:额外的有用评论来自@ChrisNeilsen。

要测试 n 是否为质数,您只需要测试 n 的平方根的可除性。而且您只需要测试先前检测到的素数的可分性。您甚至可以跳过 n.

的值

这是一个稍微更高效的代码版本。修改了两件事:

a) 由于1是not considered prime,外层循环从2.

开始

b) 默认情况下,数字被认为是质数。如果它被检测为非素数,则停止进一步检查。 (在发布的代码中,每次检查检测到一个数字为非素数时都会设置值 p = 1。每次设置 p=1 时递增计数器表明它已设置 1059 次。)

Option Explicit
Sub generatePrimes()
    Dim flag As Boolean
    Dim n, i As Integer
    For n = 2 To 100
       flag = True
        For i = 2 To n - 1
          If n Mod i = 0 Then
             flag = False
             Exit For
          End If
        Next
        If flag = True Then
          Debug.Print i
        End If
    Next
End Sub

输出:

 2 
 3 
 5 
 7 
 11 
 13 
 17 
 19 
 23 
 29 
 31 
 37 
 41 
 43 
 47 
 53 
 59 
 61 
 67 
 71 
 73 
 79 
 83 
 89 
 97 

在复习我的 VBA 技能时遇到了这个问题。这是我使用 Sieve of Eratosthenes 算法和 6k ± 1 优化并忽略所有偶数和 5 的除数的解决方案。

我创建了 2 个模块来分离逻辑和实用功能。打印第一个 100,000 个质数 10 seconds 大约

模块 1 (PrimeNumber):

Option Explicit

Sub PrintPrimes()

Dim count As Long
Dim s As Object
Dim primes As New ArrayList
Dim startTime As Date
Dim endTime As Date

startTime = Now

Set s = Sheet1.Cells
count = s(1, 2) - 1

Set primes = GetPrimeList(count)

PrintArray primes, "Sheet1", 2
endTime = Now

s(1, 3) = "Elapsed time: " & ElapsedTime(endTime, startTime)

End Sub

Function GetPrimeList(count) As ArrayList

Dim primeList As New ArrayList
Dim i As Long
Dim currentInt As Long

i = 2
primeList.Add (2)
currentInt = 3

Do While (primeList.count <= count)
    If IsPrime(currentInt) Then primeList.Add (currentInt)
    currentInt = currentInt + 2 'ignore even numbers
Loop

Set GetPrimeList = primeList

End Function

Function IsPrime(number)

Dim i As Long
Dim maxValidator As Long
Dim possiblePrime As Boolean

i = 3
IsPrime = True
possiblePrime = False
maxValidator = Round_Up(Sqr(number))

If number = 3 Then
    IsPrime = True
    Exit Function
ElseIf number Mod 5 = 0 And number > 5 Then
    IsPrime = False
    Exit Function
End If

If (number Mod 6 = 1 Or number Mod 6 = 5) Then possiblePrime = True

If possiblePrime Then
    Do While (i <= maxValidator)
        If number Mod i = 0 Then
            IsPrime = False
            Exit Do
        End If
        i = i + 2 'ignore even divisors
    Loop
Else
    IsPrime = False
End If

End Function

模块 2(实用程序):

Option Explicit

Function Round_Up(ByVal d As Double) As Long
    Dim result As Long
    result = Math.Round(d)
    If result >= d Then
        Round_Up = result
    Else
        Round_Up = result + 1
    End If
End Function

Function PrintArray(Data, SheetName As String, intStartRow As Integer)

    Dim oWorksheet As Worksheet
    Dim item As Variant
    Dim i As Long
    Set oWorksheet = ActiveWorkbook.Worksheets(SheetName)

    i = intStartRow
    For Each item In Data
        oWorksheet.Cells(i, 1) = item
        i = i + 1
    Next

End Function

Function ElapsedTime(endTime As Date, startTime As Date)
    Dim strOutput As String
    Dim Interval As Date

    ' Calculate the time interval.
    Interval = endTime - startTime

    ' Format and print the time interval in days, hours, minutes and seconds.
    strOutput = Int(CSng(Interval)) & " days " & Format(Interval, "hh") _
        & " Hours " & Format(Interval, "nn") & " Minutes " & _
        Format(Interval, "ss") & " Seconds"
    ElapsedTime = strOutput

End Function

在单元格 B1 中输入要列出的质数个数。

Alt+F8,然后按select PrintPrimes(默认情况下应该是select),然后单击Run

瞧!素数列表将从单元格 A2 打印出来。 单元格 A1 留空供用户输入,例如 输入要打印的素数

注: 我使用 Long 数据类型来覆盖更多值,而不是 Integer。如果您需要打印的值多于 2,147,483,647,则只需将 PrimeNumber 模块中的 Long 替换为 Double。在 Double 数据类型的情况下,您将看到显着的性能下降!

PS: 确保提前绑定 mscorlib.dll 使用 this link