I'd firstly like to say I'm a beginner in vb.net and coding in general.
I'm trying to find the mean of the numbers in an array.
So far, my code is this.
Function getMean() As Double
Dim DblArray(lstbxInput.Items.Count - 1) As Double
Dim totalsum As Double
Dim i As Integer
For i = 0 To dblArray.Length - 1
totalsum += DblArray(i)
Next i
dblmean = totalsum / DblArray.Length
Return dblmean
End Function
In the end, I need for dblmean to return the mean value of the dblarray numbers.
Would this be correct?
Well obviously it's wrong because I tried to print the value on a label and it always comes out as zero. Why?
Is there something wrong with the code? or was there something wrong in printing out the value?
Also, this is the code used to print out dblmean
lblLrgAns.Text = dblmean.ToString
it happens when i click a button.
A simple approach is to use the Enumerable.Average extension method which is sitting in the System.Linq namepsorts(so remember to add the Import).
Dim mean As Double = DblArray.Average()
In your case you need to initialize the array first. I guess the items in lstbxInput are already doubles.
Dim DblArrayAs As Double() = lstbxInput.Items.Cast(Of Double)().ToArray()
When you do this
Dim DblArray(lstbxInput.Items.Count - 1) As Double
All of DblArray items are 0, but you never change any of the DblArray items in your code, so dblmean would also be 0. You need to assign each item of DblArray before calculating the mean.
I would guess this is related to your previous question: putting a list into an array?, so here's how your code should look like
Function getMean() As Double
Dim DblArray(lstbxInput.Items.Count - 1) As Double
'get the items from lstbxInput
getNumbers(DblArray)
Dim totalsum As Double
Dim i As Integer
For i = 0 To dblArray.Length - 1
totalsum += DblArray(i)
Next i
dblmean = totalsum / DblArray.Length
Return dblmean
End Function
Related
The code block computes two values for speeds; Vsf and Vro using their corresponding parameter values: Angle, Super-elevation and Radius for each iteration of the for- loop statement. During each loop, it selects the minimum of both speed values. In some scenario's, Angle, super-elevation but most of all, Radius are all null values, leading to Vsf and Vro values of null and hence Vmin of null. I want to eliminate these scenarios and produce just non-zero values for Vmin hence my question.
For i = 1 To CInt(txtNumSections.Text)
ReDim Preserve Vsf(i)
ReDim Preserve Vro(i)
ReDim Preserve Vmin(i)
Vsf(i) = (((0.91544 - 0.00166 * Angle(i) - 0.000002 * W - 0.054248 * Superelevation(i) - Sidefrictionfactor) / 0.013939) * Radius(i)) ^ 0.5
Vro(i) = (((1.05653 - 0.004861 * Angle(i) - 0.000004 * W - 0.314653 * Superelevation(i) - rolloverthreshold) / 0.012729) * Radius(i)) ^ 0.5
Vmin(i) = Math.Min(Vsf(i), Vro(i))
If Vmin(i) <= "0" Then
Vmin(i) = "0"
End If
Next
Dim myList = New List(Of Double)
For Each s In Vmin
If Not String.IsNullOrWhiteSpace(s) Then
myList.Add(s)
End If
Next
Vmin = myList.ToArray()
Since arrays are immutable(you can't add or remove items) you can just re-create it:
myArray = myArray.Where(Function(s) Not String.IsNullOrEmpty(s)).ToArray()
This is a String() but this LINQ query works similar with any other type of array.
A non-LINQ appproach would be to fill a List(of T) and then use ToArray:
Dim myList = New List(Of String)
For Each s In myArray
If Not String.IsNullOrEmpty(s)
myList.Add(s)
End If
Next
myArray = myList.ToArray()
You see that LINQ can make your code more readable and understandable.
Alright guys, I found a workaround this, based on the purpose of the code piece. I simply set all null or negative values to the maximum allowable values. There's some context to it which makes it a sensible approach but I would need to explain the entire operation of the code block which I'm not sure you would have any interest in. Anyway, thanks for your contributions. They are very much appreciated
So I created an n x 2 array to hold some figures I would be inputting at runtime. Then I went ahead to add code which would add the values to the array. I wanted to know if the array was populated properly so I added code to populate a listbox with each figure inputted. However I don't think the array is populating as I think it should because the listbox isn't updating. The relevant code section is below;
N_secteion = txtNumSections.Text
Dim input_info(,) As Double = New Double(N_secteion - 1), 1) {}
Dim intIndexGrade As Integer
Dim intIndexLength As Integer
For intIndexGrade = 1 To N_secteion - 1
input_info(intIndexGrade - 1, 0) = Grade(intIndexGrade)
ListBox1.Items.Add(input_info(intIndexGrade - 1, 0).ToString())
Next
Grade(intIndexGrade) extracts values from another listbox on the form as the loop continues. This doesn't seem to be a problem since I've monitored it and it seems to pick up these values just fine. I would really appreciate some help. Been at this for too long.
N_secteion = txtNumSections.Text
Dim input_info(,) As Double = New Double((N_secteion - 1), 1) {}
Dim intIndexGrade As Integer
Dim intIndexLength As Integer
For intIndexGrade = 1 To N_secteion
input_info(intIndexGrade - 1, 0) = Grade(intIndexGrade)
ListBox1.Items.Add(input_info(intIndexGrade - 1, 0).ToString())
Next
So the issue was I wasn't looping through intIndexGrade enough times. Once this was corrected, the ListBox began to populate with all the values of the array variable because it only did so once the loop was complete.
I got a few arrays and I want to do the following math operation:
For i As Integer = 10 To 100
TransmissionArray(i) = (maxFirstArray(i) - mintranArray(i)) / (maxSecondArray(i) - mintranArray(i))
i = i + 1
Next
The problem is that sometimes mintranArray(i) has higher values than maxFirstArray(i) and maxSecondArray(i). So the program crashes.
With Try Catch the program is not shutting down but I only get TransmissionArray() = Nothing.
Sounds like your TransmissionArray isn't being initialized properly. If you just Dim it like this:
Dim TransmissionArray() As Double
Then it will be Nothing. If you try to assign a value to it in this way, you will get an exception. Normally you can insert a number in the parenthesis (Dim TransmissionArray(10) As Double) and you would have an array of length 10 that you could immediately start assigning values to. But, if you don't know the length before hand, I can think of two options that would work:
Dim TransmissionArray() As Double
For i As Integer = 10 To 100
ReDim Preserve TransmissionArray(i) 'This will increase the size of the array to the value of i, the Preserve keyword also saves the data already stored in the array
TransmissionArray(i) = (maxFirstArray(i) - mintranArray(i)) / (maxSecondArray(i) - mintranArray(i))
'i = i + 1 'Commented this out...i is already incremented once each loop
Next
Or, switch to using a List(Of Double):
Dim TransmissionArray As New List(Of Double)
For i As Integer = 10 To 100
TransmissionArray.Add((maxFirstArray(i) - mintranArray(i)) / (maxSecondArray(i) - mintranArray(i)))
'i = i + 1 'Commented this out...i is already incremented once each loop
Next
Note that the second method would make TransmissionArray 10 items less than the other arrays, due to the fact you are starting the For loop counter at 10, and just adding items to the list.
I'm quite new at using arrays and functions in Visual Basic and I cannot seem to figure this out. My problem is that whenever I call the function Fibo it returns 0 no matter the value of n I give it. I'm sure the error is pretty basic.
Any pointer would be really appreciated!
Public Function fibo(n As Integer) As Integer
Dim arrayFib(n + 1) As Integer 'declare array to hold fibonacci
arrayFib(0) = 0 'idem
arrayFib(1) = 1 'declare start value
Dim i As Integer = 2 'start position
While i <= n
arrayFib(i) = arrayFib(i - 1) + arrayFib(i - 2)
i = 1 + i
Return arrayFib(i)
Dim arrayFib(n + 1) As Integer 'declare array to hold fibonacci
We can sort of guess where that +1 came from. You added it because your original code crashed with an IndexOutOfRangeException. Caused by you returning arrayFib(i), i was incremented to be larger than n, its value is n+1 after the loop. And thus returns the value of an element that was never assigned. You didn't fix it correctly :)
Fix the array declaration back the way it was and return arrayFib(n) instead.
I am fairly new to excel vba and I can't seem to fix this problem with vbArrays. I created the function cumsum in vba just to make my life easier. However, I want to make the code flexible such that I can pass in both variants from a function and also a range. In my code, when I added the line vec=vec.value if I am passing in a range, it works perfectly fine but it doesn't work if I want it to work if I call the function and pass in a non range type. What I noticed was if I didn't have the line vec=vec.value in my code and I pass in a range, it has dimension 0 and I checked by writing my own function. Can someone please explain to me how I can fix this problem? Thanks.
Public Function cumsum(vec As Variant) As Variant
Dim temp() As Variant
MsgBox (getDimension(vec))
'works if i use vec=vec.value if vec is a range but has 0 if i do not vec = vec.values
ReDim temp(LBound(vec, 1) To UBound(vec, 1), 1 To 1) As Variant
Dim intCounter As Integer
For intCounter = LBound(vec) To UBound(vec)
If intCounter = LBound(vec) Then
temp(intCounter, 1) = vec(intCounter, 1)
Else
temp(intCounter, 1) = temp(intCounter - 1, 1) + vec(intCounter, 1)
End If
Next
cumsum = temp()
End Function
Function getDimension(var As Variant) As Integer
On Error GoTo Err:
Dim i As Integer
Dim tmp As Integer
i = 0
Do While True:
i = i + 1
tmp = UBound(var, i)
Loop
Err:
getDimension = i - 1
End Function
Why don't you just check the data type of vec by using VarType and TypeName then perform the necessary manipulation on vec
Public Function cumsum2(vec As Variant) As Variant
MsgBox TypeName(vec)
MsgBox VarType(vec)
cumsum2 = 0
End Function
The answers from #Jake and #chris are hints in the right direction, but I don't think they go far enough.
If you are absolutely sure that you'll only ever call this routine as a UDF (i.e. from formulas in your worksheets), then all you really need to do is add this:
If IsObject(vec) Then
Debug.Assert TypeOf vec Is Range
vec = vec.Value2
End If
to the start of your function. Called as a UDF, the only object type it should ever get passed is Range. Also, called as a UDF, you can rely on the fact that any arrays it gets passed will be indexed starting from 1.
I could pick out other problems with your routine, but they would be beside the point of your original question. Briefly: this will only work on column vectors, it will fail for single-cell ranges, etc.
Note that the reason your getDimension function is returning zero for Ranges because UBound is choking on the range. Your error handler happily catches an error (type mismatch) you didn't really expect to get and returning zero. (That method of finding "dimension" is assuming the error will be a subscript out range error.)
I wrote an answer a while back describing why, when working with Excel, I don't think the general getDimension approach is a good one:
https://stackoverflow.com/a/6904433/58845
Finally, the issue with VarType is that, when passed an object that has a default property, it will actually return the type of the property. So VarType(<range>) is going to tell you the type of the stuff in the range, not the code for object, because Range has a default property, Range.Value.
Modify your getDimension to include
If TypeName(var) = "Range" Then
var = var.Value
End If