Самая большая проблема, которую я вижу, это использование Single
вместо Integer
или Long
. Простые числа являются положительными целыми числами и не рассматриваются в контексте десятичных значений (насколько я знаю). Таким образом, используя синглы и сравнивая их с разделенными целочисленными значениями, вы открываете себя для неприятных ошибок разброса по краям.
Строка If N / D = Int(N / D) Then
использует плохой метод, чтобы увидеть, являются ли числа простыми. предполагает , что каждый раз, когда вы делите число с плавающей запятой (в данном случае, одиночное) на делитель, если у него есть десятичный остаток, то целочисленное преобразование этого остатка не будет равным. Однако я иногда сталкиваюсь с ошибками округления с числами с плавающей запятой при попытке сравнить ответы, и в целом я научился избегать использования преобразований с плавающей запятой в int для сравнения чисел.
Вот код, который вы можете попробовать вместо этого. Некоторые вещи на заметку:
- Я изменил типы N и D, чтобы они были длинными, а не одиночными. Это означает, что они не являются числами с плавающей запятой и подвержены возможным ошибкам округления.
- Я также явно преобразовал значение ячейки в long. Таким образом, вы узнаете в своем коде, что не работаете с типом с плавающей точкой.
- Для сравнения я использовал
Mod
, который возвращает остаток от N
, деленный на D
. Если остаток равен 0, он возвращает true, и мы знаем, что у нас нет простого числа. (Примечание: Remainder часто используется с \
, который возвращает только целочисленное значение результата деления. Mod
и \
обычно используются при точном делении целочисленных типов, что в этом случае очень подходит
- Наконец, я изменил ваше сообщение, чтобы показать фактическое сравниваемое число. Поскольку число в ячейке преобразуется, если пользователь вводит значение с плавающей запятой, ему будет полезно посмотреть, во что оно было преобразовано.
Вы, вероятно, также заметите, что этот код работает на намного быстрее, чем ваш код, когда вы добираетесь до больших чисел в сотни миллионов.
«
Sub GetPrime()
Dim N As Long
Dim D As Long
Dim tag As String
N = CLng(Cells(2, 2))
Select Case N
Case Is < 2
MsgBox N & " is not a prime number"
Case Is = 2
MsgBox N & " is a prime number"
Case Is > 2
D = 2
Do
If N Mod D = 0 Then
MsgBox N & " is not a prime number"
tag = "Not Prime"
Exit Do
End If
D = D + 1
Loop While D <= N - 1
If tag <> "Not Prime" Then
MsgBox N & " is a prime number"
End If
End Select
End Sub
ПРИМЕЧАНИЕ. Я изменил название процедуры на GetPrime
. В вашем коде у вас было:
Private Sub CommandButton1_Click()
В строке выше вы определяете процедуру (также называемую метод или иногда просто называемую sub ). Слово Sub
указывает, что вы определяете процедуру в коде, который не возвращает значения. (Иногда вы можете увидеть слово Function
вместо Sub
. Это означает, что процедура возвращает значение, например Private Function ReturnANumber() As Long
.) Процедура (Sub
) - это фрагмент кода, который будет выполняться при вызове. Также стоит отметить, что макрос Excel хранится в VBA как Sub
процедура.
В вашей строке кода CommandButton1_Click()
- это имя процедуры. Скорее всего, это было создано автоматически путем добавления кнопки в таблицу Excel. Если кнопка привязана к электронной таблице Excel, CommandButton1_Click()
будет выполняться при каждом нажатии кнопки.
В вашем коде Private
обозначает область действия процедуры. Private
обычно означает, что процедура не может быть вызвана вне модуля или класса, в котором она находится. В моем коде я пропустил Private
, потому что вы можете вызвать GetPrime
из другого модуля кода.
Вы упомянули в своих комментариях, что вам пришлось изменить название моей процедуры с GetPrime()
на CommandButton1_Click()
. Это, безусловно, работает. Тем не менее, вы также можете просто позвонить GetPrime
из в CommandButton1_Click()
, как показано ниже:
Private Sub CommandButton1_Click()
'The following line of code will execute GetPrime() '
'Since GetPrime does not have parameters and does not return a value, '
'all you need to do is put the name of the procedure without the () '
GetPrime
End Sub
'Below is the entire code for the Sub GetPrime() '
Sub GetPrime()
'The body of the code goes below: '
' ... '
End Sub
Надеюсь, это помогло немного объяснить VBA для вашего понимания!