I've encountered a problem with a program I'm writing for school. I need to verify credit card numbers using the Luhn Algorithm, however I'm having some difficulty in getting the logic of the algorithm to work correctly. I believe I know where the problem is, but I'm unable to fix it.
I believe the problem is here:
For i = 0 To cardInput.Text.Length - 2 Step -2
Dim x = (i * 2)
If x > 9 Then
x = x - 9
End If
oddTotal += x
Next
'Sum of undoubled digits
For i = 0 To cardLength - 1 Step -2
evenTotal += i
Next
total = oddTotal + evenTotal
checkSum = total
infoOutput.Items.Add("CheckDigit: " & checkDigit)
infoOutput.Items.Add("CheckSum :" & checkSum)
'Verify that the card is valid by the Mod 10 (Lund algoritm)
If checkSum = checkDigit Or checkSum = 0 Then
valid = True
Else
valid = False
End If
If it's needed, the rest of my project can be seen here
My code doesn't seem to start at the last digit and take every other digit back to the beginning to be doubled. Is the Step -2 operator incorrect here? What am I doing wrong?
There are several problems here. Particularly:
If you want a loop to count backwards, you have to start at the higher index and end at the lower one. So:
For i = cardInput.Text.Length - 2 To 0 Step -2
Then, instead of using i directly, you should use the i-ith digit:
Dim x = Val(cardInput.Text(i))
The same applies to your sum of evens.
If you want to check if the last digit is zero, use the Mod operator:
valid = (checkSum Mod 10 = 0)
Related
So, this is a two part question but based on the same project. I am trying to write a small program that can illustrate how a computer can quickly crack a password, using a brute force attack. It only has three inputs: A check box to denote if it should use integers, a check box to denote if it should use letters, and a textbox to enter the password to be cracked. It then outputs the number of combinations. Here is my code:
dim a,b,c,d,P as double
'Using the following formula:
'P(n,r) = n!/(r!(n-r)!)
'Let's assume we are just using numbers, so n = 10
'r = the count of characters in the textbox.
a = factorial(n)
b = factorial(r)
c = (n - r)
d = factorial(c)
P = a / (b * d)
Output = "With a password of " & r & " characters and " & n & " possible values, the number of combinations are " & P
Me.RichTextBox1.Text = Output & vbCrLf
Function factorial(ByVal n As Integer) As Integer
If n <= 1 Then
Return 1
Else
Return factorial(n - 1) * n
End If
End Function
So, let's assume I'm only looking at the characters 0-9, with the following number of characters in a password, I get:
P(10,1) = 10!/(1! * (10-1)!) = 10
P(10,2) = 10!/(2! * (10-2)!) = 45
P(10,3) = 10!/(3! * (10-3)!) = 120
P(10,4) = 10!/(4! * (10-4)!) = 210
P(10,5) = 10!/(5! * (10-5)!) = 252
P(10,6) = 10!/(6! * (10-6)!) = 210
P(10,7) = 10!/(6! * (10-7)!) = 120
You can see the number of combinations goes down, once it gets past 5. I assume this is right, but wanted to check before I present this. Is this because the total number in the pool remains the same, while the sample increases?
My second question is about how to consider a password to crack that repeats numbers. Again, let's assume that we are just pulling from digits 0-9. If the sample size it two (lets say 15), then there are 45 possible combinations, right? But, what if they put in 55? Are there still 45 combinations? I suppose the computer still needs to iterate over every possible combination, so it would still be considered 45 possibilities?
Function f(n)
s = 0
i = 1
while i < 7n^1/2 do
j = i
while j > 5 do
s = s + i -j
j = j -2
end
i = 5i
end
return s
end f
I am trying to solve the running time for big theta with the code above. I have been looking all over the place for something to help me with an example, but everything is for loops or only one while loop. How would you go about this problem with nested while loops?
Let's break this down into two key points:
i starts from 1, and is self-multiplied by 5, until it is greater than or equal to 7 sqrt(n). This is an exponential increase with logarithmic number of steps. Thus we can change the code to the following equivalent:
m = floor(log(5, 7n^(1/2)))
k = 0
while k < m do
j = 5^k
// ... inner loop ...
end
For each iteration of the outer loop, j starts from i, and decreases in steps of 2, until it is less than or equal to 5. Note that in the first execution of the outer loop i = 1, and in the second i = 5, so the inner loop is not executed until the third iteration. The loop limit means that the final value of j is 7 if k is odd, and 6 if even (you can check this with pen and paper).
Combining the above steps, we arrive at:
First loop will do 7 * sqrt(n) iterations. Exponent 1/2 is the same as sqrt() of a number.
Second loop will run m - 2 times since first two values of i are 1 and 5 respectively, not passing the comparison.
i is getting an increment of 5i.
Take an example where n = 16:
i = 1, n = 16;
while( i < 7 * 4; i *= 5 )
//Do something
First value of i = 1. It runs 1 time. Inside loop will run 0 times.
Second value of i = 5. It runs 2 times. Inside loop will run 0 times.
Third value of i = 25. It runs 3 times. Inside loop will run 10 times.
Fourth value of i = 125. It stops.
Outer iterations are n iterations while inner iterations are m iterations, which gives O( 7sqrt(n) * (m - 2) )
IMO, is complex.
I am trying to do a game that has 20 rounds of play. I have assigned 0 thru 8 to represent the items in the game. I need the random number to be 90 percent of the time to be any number 0 thru 5. I need the numbers 6 and 7 to be 4 percent of the time. And, I need the 8 to be only 2 percent of the time. Below is the code I have and it works sometimes but often it generates way too many of the 6s, 7s, and 8's. The way I see the code is that it should be working most of the time correctly but does not. Is there a better way to control the random to get the percents I need to be more consistently?
' Get the random number position into array
Public Sub GetNumPositions(ByVal positions() As Integer)
' 20 rounds, each round 5 numbers
' we want 2 times (8), 4 times (6 and 7)
' 2% 8, 4% 6, 4% 7, and 90% times 0 thru 5
For i As Integer = 0 To positions.Length - 1
Dim p As Integer = rndNums.Next(100)
If p < 90 Then
positions(i) = p \ 15
ElseIf p < 94 Then
positions(i) = 6
ElseIf p < 98 Then
positions(i) = 7
Else
positions(i) = 8
End If
Next
End Sub
Your code is just fine. Here is a method to test it. It gathers some numbers and calculates their frequency:
Sub Main()
Dim count = 100000000
Dim positions(count) As Integer
Dim frequencies(9) As Integer
GetNumPositions(positions)
For Each num In positions
frequencies(num) += 1
Next
For i As Integer = 0 To 8
Console.WriteLine(i & ": " & (100.0 * frequencies(i) / count) & " %")
Next
End Sub
The result is:
0: 14.994567 %
1: 15.000016 %
2: 15.01366 %
3: 14.996542 %
4: 15.002074 %
5: 15.00325 %
6: 4.002246 %
7: 3.999337 %
8: 2.000603 %
As you can see, the frequencies match your input distribution very closely.
Having a problem with this code.
my coding is the following:
fitvalchild1 = 0
fitvalchild2 = 0
For i = 1 To 30
counter = 30
Do While counter > 0
fitvalchild1 = fitvalchild1 + child1(counter) * 2 ^ (i - 1)
fitvalchild2 = fitvalchild2 + child2(counter) * 2 ^ (i - 1)
counter = counter - 1
Loop
Next i
all the variables are declared as long...
Still i get the Error : overflow and the line highlighted is:
fitvalchild1 = fitvalchild1 + child1(counter) * 2 ^ (i - 1)
The Long datatype has a maximum size of 2,147,483,647.
2 ^ (30-1) = 536,870,912
so, depending on the value of child1(counter) and fitvalchild1, you'll easily exceed the maximum.
You're adding the value to itself with each loop, so after 4-5 loops, you'll likely get the error.
If you don't mind switching away from an integer type, you might try using Currency datatype. It has a maximum size of 922,337,203,685,477.5807
The range for the long data type is -2,147,483,648 to 2,147,483,647. The values in child1 and child2 don't need to very big to overflow since 2^29 is very close to the limit.
How do I use Excel VBA to find the minimum value of an equation?
For example, if I have the equation y = 2x^2 + 14, and I want to make a loop that will slowly increase/decrease the value of x until it can find the smallest value possible for y, and then let me know what the corresponding value of x is, how would I go about doing that?
Is there a method that would work for much more complicated equations?
Thank you for your help!
Edit: more details
I'm trying to design a program that will find a certain constant needed to graph a nuclear decay. This constant is a part of an equation that gets me a calculated decay. I'm comparing this calculated decay against a measured decay. However, the constant changes very slightly as the decay happens, which means I have to use something called a residual-square to find the best constant to use that will fit the entire decay best to make my calculated decay as accurate as possible.
It works by doing (Measured Decay - Calculated Decay) ^2
You do that for the decay at several times, and add them all up. What I need my program to do is to slowly increase and decrease this constant until I can find a minimum value for the value I get when I add up the residual-squared results for all the times using this decay. The residual-squared that has the smallest value has the value of the constant that I want.
I already drafted a program that does all the calculations and such. I'm just not sure how to find this minimum value. I'm sure if a method works for something like y = x^2 + 1, I can adapt it to work for my needs.
Test the output while looping to look for the smallest output result.
Here's an Example:
Sub FormulaLoop()
Dim x As Double
Dim y As Double
Dim yBest As Double
x = 1
y = (x ^ 2) + 14
yBest = y
For x = 2 To 100
y = (x ^ 2) + 14
If y < yBest Then
yBest = y
End If
Next x
MsgBox "The smallest output of y was: " & yBest
End Sub
If you want to loop through all the possibilities of two variables that make up x then I'd recommend looping in this format:
Sub FormulaLoop_v2()
Dim MeasuredDecay As Double
Dim CalculatedDecay As Double
Dim y As Double
Dim yBest As Double
MeasuredDecay = 1
CalculatedDecay = 1
y = ((MeasuredDecay - CalculatedDecay) ^ 2) + 14
yBest = y
For MeasuredDecay = 2 To 100
For CalculatedDecay = 2 To 100
y = ((MeasuredDecay - CalculatedDecay) ^ 2) + 14
If y < yBest Then
yBest = y
End If
Next CalculatedDecay
Next MeasuredDecay
MsgBox "The smallest output of y was: " & yBest
End Sub