通过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
我找到了下面的代码,但它不起作用。请在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