Самая большая проблема, которую я вижу в использовании Single
вместо Integer
или Long
. Простые числа являются положительными целыми числами и не рассматриваются в контексте десятичных значений (насколько я знаю). Таким образом, используя синглы и сравнивая их с разделенными ints, вы открываете себя до неприятных ошибок на рулонном крае.
В строке If N/D = Int(N/D) Then
используется плохой метод, чтобы узнать, являются ли цифры первыми. Это , предполагая, что каждый раз, когда вы делите число с плавающей запятой (в данном случае на сингл) на делитель, если оно имеет десятичный остаток, то целочисленное преобразование этого остатка не будет равным. Тем не менее, я иногда сталкивался с ошибками округления с числами с плавающей запятой при попытке сравнить ответы, и в целом я научился избегать использования конверсий с плавающей точкой в int как способ сравнения чисел.
Вот какой код вы могли бы попробовать вместо этого. Некоторые примечания:
- Я изменил типы N и D так, чтобы они были длинными, а не одиночными. Это означает, что они не являются плавающей точкой и подвержены возможным ошибкам округления.
- Я также явно преобразовал значение ячейки в длинный. Таким образом, вы знаете в своем коде, что вы не работаете с типом с плавающей точкой.
- Для сравнения, я использовал
Mod
, который возвращает остальную часть N
, деленную на D
. Если остаток равен 0, он возвращает true, и мы знаем, что у нас нет простого числа. (Примечание:. Остаток часто используется с \
, который только возвращает целое значение результата деления 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
указывает, что вы определяете процедуру в коде, которая не возвращает никакого значения. (Иногда вы можете увидеть слово 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 для дальнейших вашего понимания!
Для каких чисел это не работает? В чем проблема? –
Кажется, все в порядке. Возможно, вы захотите изменить это, хотя «Loop While D <= N - 1», возможно, для «Loop While D <= N/2' для начинающих –
Работает и для меня. Единственное, о чем я могу думать, это то, что он/она не помещает фактическое число в нужное место на листе XLS (хе-хе). – ajdams