Why does my VB.NET array have extra values? - arrays

I declare my array
Dim A(N) As Integer
When I loop from 1 To N or 0 To N-1 there's an extra value at one end or the other.
What's going on?
(Intended to be a canonical question/answer.)

In VB.NET arrays almost always* have a lower bound of 0 and are declared mentioning their upper bound, not their length.
They did change the VB.NET syntax early on to allow you to remind yourself if needed:
Dim A(0 To N) As Integer
That 0 can't be anything else (such as a 1 or a constant zero).
You can loop through all VB.NET array indexes using
For i = LBound(A) To UBound(A)
or, more simply,
For i = 0 To N
(*) You can use the .NET Framework to create arrays with other lower bounds, but you need to refer to them as Array and thus with late binding (and probably Option Strict Off).

Related

For Each through single rank of multidimensional array

I have a 2D array - aArray(1,variable) and want to know how I can For Each through the first rank of the array, ie only read aArray(0 , variable)
This is more for self educational purposes as to how if possible it can be done. I can do it with a for loop:
Dim a As Integer: For a = 0 to ?
Range("A1").Value = aArray(0,a)
Next a
But was interested in using the For Each loop. So far I've got
Dim a As Variant: For Each S In aArray
Range("A1").Value = S
Next a
But it iterates through all the array (0,0) (1,0) (0,1) (1,1) Etc...
You can't do that. You'd have to output the first rank into a new array, and then iterate through that.
There's no good reason to use For Each anyway since it's slower - see: https://support.microsoft.com/en-us/kb/129931

How to find the dimensions of an array parameter in QBasic

I have a QBasic function that takes two arrays as parameters. I'd like to know if it's possible to find the number of dimensions those arrays have in the function.
For context, I'm writing an assertArrayEqual function for a QBasic unit testing library.
There is no way to accomplish this. As stated, you can determine the lower and upper bounds, but you must know beforehand how many dimensions the array contains. To my knowledge this is not even available in higher level versions.
It can be done but it is not pretty: (QB64 source).
REM sample code to find number of dimensions in an array
DIM a(2, 2, 2) AS INTEGER
DIM SHARED E AS INTEGER
ON ERROR GOTO 10
CALL array(a())
END
10 E = -1: RESUME NEXT
SUB array (a() AS INTEGER)
DO
X = X + 1
T = UBOUND(a, X)
IF E THEN
X = X - 1
PRINT "Array has"; X; "dimensions."
EXIT DO
END IF
LOOP
END SUB

Visual Basic, problems filling an arraylist

I think I'm doing something weird here or maybe I'm just not well enough informed but I'm stuck at filling my arraylist with another array (size 2).
I originally program in Java and I thought this would work in Visual Basic but I can not find a solution. So here I am!
The problem at hand:
I've got two 2D arrays and I need to take the average for each part in the array.
I loop through both of the array and perform some (easy) math. However, when it ends I get an array filled with the answer of the last made calculation.
What am I doing wrong here?
I am using Microsoft Visual Studio Express 2013
Here is the code that provides the combining of the two arrays:
Private Sub btnCombine_Click(sender As Object, e As EventArgs) Handles btnCombine.Click
'A safety to assure that the for loop will loop until the length of the
smallest array
If (dScanListMusic1.Count < dScanListMusic2.Count) Then
combineCounter = dScanListMusic1.Count
Else
combineCounter = dScanListMusic2.Count
End If
For i As Integer = 0 To combineCounter - 1
For j As Integer = 0 To 1
'Taking the average of the two doubles
joinedAverage = (dScanListMusic1(i)(j) + dScanListMusic2(i)(j)) / 2
dScanListMusicCombinedRow(j) = joinedAverage
Next
dScanListMusicCombined.Add(dScanListMusicCombinedRow)
Next

VBA arrays and Operators

I am trying to write a couple lines of code in VBA for excel, here is what the VB.Net version of the code looks like.
ThisVariable <<= 8
Variable.Add(ThisVariable)
How do I write these lines of code in VBA? VBA does not have the "<<=" operator and does not have the .Add property of an array. Any help would be greatly appreciated.
For the first question, VBA doesn't have built in bit shifting, but you can add a function that does it for you. Try this one.
For the second question, to increase an array size, you have to use the ReDim command. Here's the info on that.
Also, you could use a collection instead of an array. With a collection, you can add & delete item within it at will.
Good luck
<<= left-shifts the number by 8 binary digits, i.e. multiplies the number by 256. For adding something to an array you can re-dim the array:
ThisVariable = ThisVariable * 256
Dim U As Long
Dim L As Long
L = LBound (Variable)
U = UBound (Variable)
ReDim Preserve Variable (L To U+1)
Variable (U+1) = ThisVariable
Note that redim'ing the array just to add an element is not very efficient. You should try to find another approach (e.g. use a larger array and store the number of "valid" elements in a counter variable -- or even create a class module for that).

Operating elementwise on an array

I'm trying to check if my arrays are returning nonsense by accessing out of bounds elements, in fortran. And I want to check these values are less than one, and if they are, change them to one.
This is the piece of my code causing issues:
lastNeighLabel=(/clusterLabel(jj-1,kk,ll), clusterLabel(jj,kk-1,ll), clusterLabel(jj,kk,ll-1)/)
LastNeighLabel contains the cluster label (between 1 and n, where n isthe total number of unique seperate clusters found) for the last neighbour in the x,y,z direction respectively.
When jj or kk or ll are 1, they try and access the 0th element in the array, and as FORTRAN counts from 1 in arrays, it tries to destroy the universe. I'm currently in a tangled mess of about 8 if/elseif statements trying to code for every eventuality. But I was hoping there was a way of operating on each element. So basically I'd like to say where((/jj-1,kk-1,ll-1/).lt.1) do clusterLabel(jj-1,kk,ll)=0 etc depending on which element is causing the problem.
But I can't think of a way to do that because where will only manipulate the variables passed to it, not a different array at the same index. Or am I wrong?
Will gladly edit if this doesn't make sense.
It is not obligatory that Fortran accesses arrays starting from one. Any starting value is allowed. If it more convenient to you to have a zero indexed array, declare the array as:
real, dimension (0:N-1, 0:M-1) :: array
Or
real, dimension (0:N, 0:M) :: array
and have the 0 indices be extra to catch special cases.
This might be another solution to your problem, since zero index values would be legal.
Another possible way to approach this, is to create an extended cluster label array (with index bounds starting at 0), which is equal to the cluster label array with a layer of zeroes tacked on the outside. You can then let your loop run safely over all values of jj, kk, and ll. It depends on the size of the array if this is a feasible solution.
integer :: extended_cluster_label(0:size(cluster_label,1), &
0:size(cluster_label,2), &
0:size(cluster_label,3) &
)
extended_cluster_label(0,:,:) = 0
extended_cluster_label(:,0,:) = 0
extended_cluster_label(:,:,0) = 0
extended_cluster_label(1:, 1:, 1:) = cluster_label
Maybe you could use a function?
real function f(A,i,j,k)
real :: A(:,:,:)
integer :: i,j,k
if (i==0.or.j==0.or.k==0) then
f=0
else
f=A(i,j,k)
endif
end function f
and then use f(clusterLabel,jj-1,kk,ll) etc.

Resources