In the below example code from a tutorial, I understand how the majority of it works. There are a few things I do not understand, though. Please help me to understand the purpose of some of these characters and the purpose of them. I will explain below what I don't understand.
Module paramByref
Sub swap(ByRef x As Integer, ByRef y As Integer)
Dim temp As Integer
temp = x ' save the value of x
x = y ' put y into x
y = temp 'put temp into y
End Sub
Sub Main()
' local variable definition
Dim a As Integer = 100
Dim b As Integer = 200
Console.WriteLine("Before swap, value of a : {0}", a)
Console.WriteLine("Before swap, value of b : {0}", b)
' calling a function to swap the values '
swap(a, b)
Console.WriteLine("After swap, value of a : {0}", a)
Console.WriteLine("After swap, value of b : {0}", b)
Console.ReadLine()
End Sub
End Module
What I don't understand is why the need for x, y, and temp. why not just keep declaration of a and b and swap the values?
Also, on the Console.WriteLine, I understand the {0} is an nth reference or index position, but the comma suggests to output something else. Is it saying to output the value of a in the 0 index? If so, there can only be one zero index, so why does the next line reference the value of the zero index? Or am I all wrong on this? Any explanation would be greatly appreciated...please dumb your answer down for this newbie.
The reason for x, y, and temp is to demonstrate how to do swapping. Your question asks
why not just keep declaration of a and b and swap the values
In this situation where you aren't doing any incrementing, sure you could just afterward say b = 100 and a = 200 but if you were doing this say in a loop and constantly swapping them, if you were to do
a = b
b = a
you would have a=100, b=100 because you set the value of b = a which is 100, then set a as the same value so it is still 100. That's why you need the temp value.
With regards to the console.writeLine, you are absolutely correct that it is indexing the 0th index, so in the first example, it is a, however it can be reused in the next line, because it is a totally separate line of code. Each of those console.writeLines can exist independently, so the values are indexed on a line by line basis
You need a temp to store the value from the first var so that you do not lose it when you overwrite it with the value from the second var. Once the second var's value has been transferred into the first var, the value stored in temp (from the original first var) can be transferred into the second var (overwriting the original value).
This is a common method when creating custom sorting routines that shuffle the values from various positions and ranks in an array around.
a and b are variables that are only visible in method Main(). They cannot be accessed from a different method. On the other hand, x, y, and temp are variables that are only visible in method swap(). More precisely, x and y are the method's parameters. The keyword ByRef means that the parameters are references to variables. I.e. when you call swap(a, b), x becomes a reference to variable a and y becomes a reference to variable b. You can work with references like with other variables. The difference is that when you change x in swap(), a in Main will change accordingly.
The Console.WriteLine() method takes a string parameter and an arbitrary number of additional parameters. The {0} is an index into the list of those additional parameters. E.g. Console.WriteLine("{0} {1} {2}", 100, 200, 300) would output 100 200 300. and Console.WriteLine("{2} {1} {0}", 100, 200, 300) would output 300 200 100.
Related
Let's say I have a set:
S: Id X Counter
Id: \nat
Counter: \nat
Need help to define an operation filter which takes in two parameters, x:\nat and y:\nat which I can apply to S. This function will match on the first parameter with \exists a \in S # first(a) = x and then reduce second(a) with y. If the value is less than or equal to zero, a should be removed from the set S, otherwise (first(a), second(a) - y) should replace a.
If the above is indecipherable, just please give me any example definition that operates over a set and modifies it.
Thanks.
Supposing I have a class
Public Class Foo
Property fooProp1 as Single
Property fooProp2 as Single
Property fooProp3 as Single
End Class
to find the absolut maximum of a property (which contains positive or negative values) in a Collection(Of Foo) I can do:
Collection.Max(Function(x As foo) Math.Abs(x.fooProp1))
and it returns the greater absolute value WITHOUT sign.
The question is how can I do to get the number WITH sign?
Thanks in advance.
RG
Math.Abs will always return an unsigned value (the actual meaning of Absolute).
The get the value of a property you need only to READ it.
To get a MAX or MIN, you MUST compare values, like this:
dim x as integer = foo.property
dim y as integer = last_foo_property (or anything else)
Minimum = Math.Min(x,y)
Maximum = Math.Max(x,y)
But, if are trying to get the lower and upper values of a collection, you may utilize:
MaxValue = Collection.Find(Collection, Function(Z) (Z > BiggerValue))
MinValue = Collection.Find(Collection, Function(Z) (Z < LowerValue))
where these values are gotten before the call.
Another way is to make a SORT and get the first and the last values...
Collection.Select(Function(x) a.fooProp1).Aggregate(Function(a, b)
If(Math.Abs(a) > Math.Abs(b), a, b))
Hi I am trying to create a function that takes as input a few parameters (irrelevant to the variables optimized) and a variable over which I want to optimize. For example for foo_function(a,b,c,x) I want to pass a,b,c as fixed parameters to foo_function, and finding the minimum of foo_function by changing x. If I was able to work in Matlab or Python this should be relatively easy as a function can return a handle to another function, but that's not possible in VBA. Im trying to use the code in http://www.quantcode.com/modules/mydownloads/singlefile.php?lid=424
Does anybody have any idea how to proceed?
You can declare foo_function to take a parameter array, treat it as a function of 1 variable if only 1 parameter is passed, and if more than 1 is passed, you can store the parameters in static variables. This allows your calling code to set the parameters of foo_function before passing its name to optimization code which will treat it as a function of 1 variable.
As a proof of concept, the following function represents a quadratic function:
Function quad(ParamArray args()) As Double
Dim x As Double
Static a As Double
Static b As Double
Static c As Double
If UBound(args) = 0 Then
x = args(0)
Else 'assumes that at least 3 parameters passed
a = args(0)
b = args(1)
c = args(2)
If UBound(args) = 3 Then
x = args(3)
Else
Exit Function 'function call just initializes statics
End If
End If
quad = a * x ^ 2 + b * x + c
End Function
When just 1 is passed, quad(x) just evaluates ax^2 + bx + c with its current values for those coefficients. If 4 is passed then it is interpreted as a call to quad(a,b,c,x), with the obvious meaning. If just 3 parameters are passed, it is called like a sub:
quad a,b,c
and doesn't return anything but sets the static parameters to the passed values.
To test it, I wrote a crude numerical differentiation function:
Function Derivative(f As String, x As Double, h As Double) As Double
Derivative = (Application.Run(f, x + h) - Application.Run(f, x)) / h
End Function
This approximates the derivative of f at the given x value using the given step size.
The following test sub shows how quad can be set before passing it the the derivative function:
Sub test()
quad 1, 2, -3 'initializes quad to be x^2 + 2x - 3
Debug.Print Derivative("quad", 2, 0.0001) 'should be approximately 6
quad 3, 2, 1
Debug.Print Derivative("quad", 2, 0.0001) 'now around 14
End Sub
Output:
6.00010000001205
14.0003000000277
Another, in some ways simpler, approach is to use public variables instead of actual parameters for the parameters to foo_function that are irrelevant to the variables being optimized. Then the calling code could assign to these public variables before optimizing. This approach would eliminate the need for parameter arrays but has the drawback of using global-type variables which tend to make programs not sufficiently modular.
I'm sorry the title is so confusingly worded, but it's hard to condense this problem down to a few words.
I'm trying to find the minimum value of a specific equation. At first I'm looping through the equation, which for our purposes here can be something like y = .245x^3-.67x^2+5x+12. I want to design a loop where the "steps" through the loop get smaller and smaller.
For example, the first time it loops through, it uses a step of 1. I will get about 30 values. What I need help on is how do I Use the three smallest values I receive from this first loop?
Here's an example of the values I might get from the first loop: (I should note this isn't supposed to be actual code at all. It's just a brief description of what's happening)
loop from x = 1 to 8 with step 1
results:
x = 1 -> y = 30
x = 2 -> y = 28
x = 3 -> y = 25
x = 4 -> y = 21
x = 5 -> y = 18
x = 6 -> y = 22
x = 7 -> y = 27
x = 8 -> y = 33
I want something that can detect the lowest three values and create a loop. From theses results, the values of x that get the smallest three results for y are x = 4, 5, and 6.
So my "guess" at this point would be x = 5. To get a better "guess" I'd like a loop that now does:
loop from x = 4 to x = 6 with step .5
I could keep this pattern going until I get an absurdly accurate guess for the minimum value of x.
Does anybody know of a way I can do this? I know the values I'm going to get are going to be able to be modeled by a parabola opening up, so this format will definitely work. I was thinking that the values could be put into a column. It wouldn't be hard to make something that returns the smallest value for y in that column, and the corresponding x-value.
If I'm being too vague, just let me know, and I can answer any questions you might have.
nice question. Here's at least a start for what I think you should do for this:
Sub findMin()
Dim lowest As Integer
Dim middle As Integer
Dim highest As Integer
lowest = 999
middle = 999
hightest = 999
Dim i As Integer
i = 1
Do While i < 9
If (retVal(i) < retVal(lowest)) Then
highest = middle
middle = lowest
lowest = i
Else
If (retVal(i) < retVal(middle)) Then
highest = middle
middle = i
Else
If (retVal(i) < retVal(highest)) Then
highest = i
End If
End If
End If
i = i + 1
Loop
End Sub
Function retVal(num As Integer) As Double
retVal = 0.245 * Math.Sqr(num) * num - 0.67 * Math.Sqr(num) + 5 * num + 12
End Function
What I've done here is set three Integers as your three Min values: lowest, middle, and highest. You loop through the values you're plugging into the formula (here, the retVal function) and comparing the return value of retVal (hence the name) to the values of retVal(lowest), retVal(middle), and retVal(highest), replacing them as necessary. I'm just beginning with VBA so what I've done likely isn't very elegant, but it does at least identify the Integers that result in the lowest values of the function. You may have to play around with the values of lowest, middle, and highest a bit to make it work. I know this isn't EXACTLY what you're looking for, but it's something along the lines of what I think you should do.
There is no trivial way to approach this unless the problem domain is narrowed.
The example polynomial given in fact has no minimum, which is readily determined by observing y'>0 (hence, y is always increasing WRT x).
Given the wide interpretation of
[an] equation, which for our purposes here can be something like y =
.245x^3-.67x^2+5x+12
many conditions need to be checked, even assuming the domain is limited to polynomials.
The polynomial order is significant, and the order determines what conditions are necessary to check for how many solutions are possible, or whether any solution is possible at all.
Without taking this complexity into account, an iterative approach could yield an incorrect solution due to underflow error, or an unfortunate choice of iteration steps or bounds.
I'm not trying to be hard here, I think your idea is neat. In practice it is more complicated than you think.
Given an enum similar to this:
Friend Enum TestValue As Int32
tstNotSet = -1
tstA = 0
tstB = 1
tstC = 2
tstD = 3
tstE = 4
tstF = 5
tstG = 6
tstH = 7
tstI = 8
tstJ = 9
tstK = 10
tstL = 11
tstM = 12
End Enum
And an Array similar to this:
Dim TestValues() As String = {"A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M"}
And a string is fed in as input in some form similar to (assume it is already stored to a variable):
Dim tmpInput As String = "ADFGHJLM"
And a Sub/Method in another arbitrary class that takes in as input an array of one of more of the Enums from TestValue, based on the input string tmpInput. Basically, I want to walk the tmpInput variable, and for each character, map out its equivalent member in the Enum, so that I can pass it to this Sub in the other object. The string array TestValues and the Enum TestValue (yes, the names could be done better, but don't let that bother you too much) are laid out to match each other explicitly.
So I basically want to search the array for the matching letter, and use its index offset to know which Enum I want to map to that letter. My current code uses a large Select Case statement, but that's just ugly (although, performance tests show it to be rather speedy, even in the debug build).
The purpose of this test case is to provide an example of a mechanism I use in a project I'm working on. In this project, objects have a ReadOnly property that returns a string of letters composed from TestValues. It also has a Sub that accepts an array of one or more Enums from TestValue that sets a private member in the object that is used by the aforementioned ReadOnly property. The purpose was to store an array of smaller integer values (the Enums) rather than an array of strings for the object's internal functionality. So I had to create a way to map back and forth between the string array and the enum.
Yes, it's easily doable with the many different collections available in .NET, but I feel those are too heavyweight for my needs, as many of my objects have enums as small as two values, hence, arrays. I borrowed the trick from a similar example used in C to be able to select a string from a const array based on an index offset.
Anyways, as I've discovered, searching arrays in VB.NET is not trivial. There is apparently no simple command like TestValues.GetIndex(tmp(i)), where tmp(i) is a variable holding a single character (String, not Char), that would return say, '8' if tmp(i) was set to 'I'. Instead, methods like Array.FindIndex require using delegates/predicates, something I haven't fully wrapped my head around just yet (they seem like function pointers from C).
So what's the best way, other than constantly looping over the array for every input character, to locate the index offset based on the stored value? Is the method I highlight sane or insane (hint: it's a hold-over from VBA code)? Is there a more efficient way?
Oh, and yes, the ReadOnly property does check that the internal members are NOT set to tstNotSet before attempting to read from the TestValues array. That's why that Enum member exists.
Thanks!
EDIT: Hopefully this doesn't muddle the explanation up too much, but here's an example, as simplified as I can get it, of how the look up currently operates using the array, enum, and input string as defined above:
Dim n As Int32 = 0
Dim Foobar(0 to 12) As TestValue
For Each s As String In tmpInput
Select Case Char.ToUpper(CChar(s))
Case CChar(TestValues(tstA))
Foobar(n) = tstA
n += 1
Case CChar(TestValues(tstB))
Foobar(n) = tstB
n += 1
Case CChar(TestValues(tstC))
Foobar(n) = tstC
n += 1
Case CChar(TestValues(tstD))
Foobar(n) = tstD
n += 1
Case CChar(TestValues(tstE))
Foobar(n) = tstE
n += 1
Case CChar(TestValues(tstF))
Foobar(n) = tstF
n += 1
Case CChar(TestValues(tstG))
Foobar(n) = tstG
n += 1
Case CChar(TestValues(tstH))
Foobar(n) = tstH
n += 1
Case CChar(TestValues(tstI))
Foobar(n) = tstI
n += 1
Case CChar(TestValues(tstJ))
Foobar(n) = tstJ
n += 1
Case CChar(TestValues(tstK))
Foobar(n) = tstK
n += 1
Case CChar(TestValues(tstL))
Foobar(n) = tstL
n += 1
Case CChar(TestValues(tstM))
Foobar(n) = tstM
n += 1
End Select
Next
As noted in my comment to Jon Skeet, this construct, along with the rest of the Object's components, executes 100,000 times in a profiling loop in ~570ms (rough average of 3-5 runs).
Exchanging the above construct out with a smaller Array.IndexOf construct loops 100,000 times in ~630ms (again, 3-5 runs, rough average, the whole Object). The new construct looks like this:
Dim p As Int32
p = Array.IndexOf(TestValues, s)
If p <> tstNotSet Then
Foobar(n) = DirectCast(p, TestValue)
n += 1
End If
I'm afraid I found your question extremely hard to understand, but is Array.IndexOf what you're looking for?
Dim index = Array.IndexOf(TestValues, tmp(i))
I've got trouble tying a rope to this question. But in any kind of lookup scenario, you always want to use a Dictionary. You'll get O(1) time instead of O(n). Something like this:
Dim lookup As New Dictionary(Of Char, TestValue)
lookup.Add("A"c, TestValue.tstA)
lookup.Add("B"c, TestValue.tstB)
'' etc
You can make the initialization cleaner in many ways. Then:
Dim value As TestValue = lookup(letter)
i would say the solution by #Hans Passant is the way to go with this, but since you are dealing with chars, and chars are numbers,there is an alternative where you dont need a Dictionary.
you could store all the TestValue enum values in an array, and do something like testValueResult = testValueArray(charCode - 65),i.e. just map 'A' to index 0,'B' to 1..., or even just a direct cast from the numeric form of the TestValue to its Enum since you do define it as an integer, and include a simple bounds check for tstNotSet too.