This is my first question here and I must admit, I was not able to find any solution so far here or elsewhere. Here is the problem:
I wanted to program a code, which is supposed to do the following:
- Ask the user how many rows are needed
- Ask, how many columns are needed
- Create a matrix, where in the first column all rows are numbered, in the first row all columns are numbered and within the matrix, all these numbers are the multiplied (row 3/column 4 contains 12, for example).
- Finally, all prime numbers shall be colored.
My problem starts with the last step (in my code beginning at “‘Primzahlen hervorheben”). For each combination of row and column I use two
for loops, in which I first assume, the product IS a prime number by setting
primzahl = true and set
k = 2, which is 1 upped through all numbers up to the product itself… BUT for some reason,
k keeps growing and eventually reaches the five digits area, before it crashes. I guess, the problem must be in this line:
Do While (primzahl = True) Or (k <= i * j) Or (i * j <> 1)
I connected all conditions as one would in an
if construct. The Editor itself does not seem to have a problem with this, but why does it ignore the second condition, which does not allow for
k to become larger than
i * j? Am I missing something?
Just to put it in words: The loop shall continue, as long as
- it being not a prime number proves to be the case (p
rimzahl = false), OR
kis smaller or equal to
i * j, OR
i * jis not 1
This case is no emergency or anything, I just want to know, where the hook is. I would appreciate your support and hope, to get some helpful advise.
Sub rechnen() 'Zellen leeren Cells.ClearContents Cells.ClearFormats 'Variablen definieren Dim i As Integer, j As Integer, k As Integer, iMax As Integer, jMax As Integer, primzahl As Boolean 'Variablen Werte zuweisen iMax = 3 'InputBox("Anzahl Zeilen") jMax = 5 'InputBox("Anzahl Spalten") 'Eigentliche Prozedur For i = 1 To iMax Cells(1 + i, 1).Value = i For j = 1 To jMax Cells(1, 1 + j).Value = j Cells(1 + i, 1 + j).Value = i * j Next j Next i 'Spaltenbreite anpassen ActiveSheet.UsedRange.Columns.AutoFit 'Primzahlen hervorheben For i = 1 To iMax For j = 1 To jMax k = 2 primzahl = True '''''''' Do While (primzahl = True) Or (k <= i * j) Or (i * j <> 1) If Cells(1 + i, 1 + j).Value Mod k = 0 Then primzahl = False Exit Do End If k = k + 1 Loop '''''''' If primzahl = True Then Cells(1 + i, 1 + j).Interior.Color = vbRed End If Next j Next i End Sub ``
You seem to be mixing up OR and AND:
The loop shall continue, as long as […] OR […] OR […]
You actually mean to say that the loop shall end when either one of these three conditions is not true. So logically the loop should continue while all of the conditions are still true. This expresses a logical AND, not an OR.
So you meant:
Do While (primzahl = True) And (k <= i * j) And (i * j <> 1)
But this can be simplified.
primzahl = True will always be true, because as soon as you set
primzahl = False, you explicitly exit the loop with
Exit Do, so the
While condition never gets evaluated with
primzahl = False.
(i * j <> 1) is true the first iteration, it will also be true in any other iteration, since the iterations do not change
j. But even if it were true the first time, then certainly
k <= i * j is not true (you already set
k = 2 and it only gets greater values), so also this condition is always going to be true once you get past the condition on
So, taking that into account you would have:
k = 2 Do While k <= i * j ' etc.. k = k + 1 Loop
And then why not make it a
For loop, since you let
k go from 2 to
For k = 2 To i * j ' etc.. (don't do k = k + 1 now) Next
Concerning the assignment you gave yourself: numbers resulting from
i * j with
j both greater than 1 are by definition not primes, so there is no sense in performing a check on them. They have at least
j as divisors.
I have finally returned, after I was absent for quite a while. With a fresh mind I just tried again to tackle the task described above. Naturally, I implemented certain changes:
First: The numbers in the matrix are no longer products of the given numbers in the first row and column, since that fully defeats the purpose of checking for prime numbers. Instead they are now random numbers, ranging from 1 to 10, to keep it simple.
Second: What my code now does , is for each cell (after receiving a random number) to FIRST ASSUME the number in question IS a prime number and color the cell red. This assumption is furthermore tested by dividing the given number with 2 then 3 then…. up to the given number-1. If one of those checks proves to be positive, i.e. the mod is equal to zero, the format of the cell is cleared and the next cell undergoes the same mechanism.
Just wanted to share this insight 🙂
Sub matrix() Cells.ClearContents Cells.ClearFormats Dim xMax As Integer, yMax As Integer, x As Integer, y As Integer, z As Integer xMax = InputBox("Anzahl Spalten") yMax = InputBox("Anzahl Spalten") Randomize For x = 1 To xMax Cells(1 + x, 1) = x For y = 1 To yMax Cells(1, 1 + y) = y Cells(1 + x, 1 + y) = Int(Rnd() * 10 + 1) z = 2 Do While z < Cells(1 + x, 1 + y).Value Cells(1 + x, 1 + y).Select ActiveCell.Interior.Color = vbRed If Cells(1 + x, 1 + y) Mod z = 0 Then Cells(1 + x, 1 + y).Select ActiveCell.ClearFormats Exit Do End If z = z + 1 Loop Next y Next x End Sub
Just found another problem: 2s are ignored, since the loop only works, if z is < 2. However, I corrected this by simply check if the number is two before the loop. If this is the case, the loop will be skipped:
Dim xMax As Integer, yMax As Integer, x As Integer, y As Integer, z As Integer
xMax = 10 'InputBox("Anzahl Spalten")
yMax = 10 'InputBox("Anzahl Spalten")
For x = 1 To xMax
Cells(1 + x, 1) = x
For y = 1 To yMax
Cells(1, 1 + y) = y
Cells(1 + x, 1 + y) = Int(Rnd() * 10 + 1)
If Cells(1 + x, 1 + y).Value = 2 Then
Cells(1 + x, 1 + y).Interior.Color = vbRed
z = 2
Do While (z < Cells(1 + x, 1 + y).Value)
Cells(1 + x, 1 + y).Interior.Color = vbRed
If (Cells(1 + x, 1 + y).Value Mod z = 0) And (Cells(1 + x, 1 + y).Value <> 2) Then
Cells(1 + x, 1 + y).ClearFormats
z = z + 1