I am very new to Matlab, and I feel completely overwhelmed by the use of arrays. What is the most efficient implementation of the following C++ code in Matlab?
A = std::vector<double>();
for (int i = 0; i < 100; i++) {
if (complicatedBoolFunction(i)) {
A.push_back(i);
}
}
Edit: By efficiency I mean to use as little resources as possible to grow the array A - that is, to avoid copy-pasting it into temporary memory
You can do this 2 ways
Pre-allocating for the maximum size, and removing unused elements. This has the advantage of pre-allocating memory in case the condition is often met...
A = NaN(100,1)
for ii = 0:99
if rand > 0.5 % some condition
A(ii+1) = ii; % some value
end
end
A(isnan(A)) = []; % remove unused elements
Appending to the array. This avoids making A way too large if appending is unlikely...
A = []; % empty array
for ii = 0:99
if rand > 0.5 % some condition
A(end+1, 1) = ii; % some value. Equivalent to 'A = [A; ii];'
end
end
A better, and more Matlab-esque way of doing this would be to vectorise your conditional function. This way you avoid looping and allocation issues...
ii = 0:99;
A = ii(rand(100, 1) > 0.5);
You can use any Boolean function you like as an indexing array, as long as it returns a logical array with the same number of elements as the array you're indexing (ii here) or integer indices of the elements to choose.
The most efficient implementation of such C++ code would be
i = 0:99;
A = i(complicatedBoolFunction(i));
Anyway you can grow an array with concatenation, which is (or was) usually not recommended, like the following
A = [];
for i = 0:99
if (complicatedBoolFunction(i))
A = [A i];
end
end
or much more efficiently like this:
A = [];
for i = 0:99
if (complicatedBoolFunction(i))
A(end + 1) = i;
end
end
how to do this?
i want to place a specific number, like number 2 randomly into a 3x3 of zeros array,
it did came out, but the coding still not right and somehow number 1 also appear.
rows = 3;
cols = 3;
M = zeros(rows,cols);
p = randi(2);
rV = randperm(rows);
cV = randperm(cols);
M(rV(2),cV(2))=p
where did i do wrong? any suggestion
You could also use randi together with linear indexing
m = zeros(3);
m(randi(numel(m))) = 2;
No need - I've already solved it!
a=[2];
m=zeros(3);
m(randperm(numel(m),numel(a)))=a
Is there a way to grow a 3D array in the third dimension using the end index in a loop in Matlab?
In 2D it can be done like
a = [];
for x = y
a(end + 1, :) = f(x);
end
But in 3D the same thing will not work as a(1,1,end) will try to index a(1,1,1) the first iteration (not a(1,1,0) as one might expect). So I can't do
im = [];
for x = y
im(:, :, end + 1) = g(x);
end
It seems the end of a in third dimension is handled a bit differently than in the first two:
>> a = [];
>> a(end,end,end) = 1
Attempted to access a(0,0,1); index must be a positive integer or logical.
Am I missing something about how end indexing works here?
What you're asking...
If you know the size of g(x), initialize im to an empty 3d-array:
im = zeros(n, m, 0); %instead of im = [];
I think your code should work now.
A better way...
Another note, resizing arrays each iteration is expensive! This doesn't really matter if the array is small, but for huge matrices, there can be a big performance hit.
I'd initialize to:
im = zeros(n, m, length(y));
And then index appropriately. For example:
i = 1;
for x = y
im(:, :, i) = g(x);
i = i + 1;
end
This way you're not assigning new memory and copying over the whole matrix im each time it gets resized!
I know that to get 10 0's, one can do
A = zeros(10, 1);
To get 10 1's, one can do
A = ones(10, 1);
What about any arbitrary number? Say, I want 10 3's. I have come up with a way of doing it.
A = linspace(3, 3, 10);
Is this satisfactory? Is there a more elegant way of doing this?
Some alternatives:
Using repmat:
A = repmat(3, [5 7]); %// 5x7 matrix filled with the value 3
Using indexing:
A(1:m, 1:n) = x;
Following is a timing comparison between all proposed approaches. As you can see, #Dennis' solutions are the fastest (at least on my system).
Functions:
function y = f1(x,m,n) %// Dennis' "ones"
y = x*ones(m,n);
function y = f2(x,m,n) %// Dennis' "zeros"
y = x+zeros(m,n);
function y = f3(x,m,n) %// Luis' "repmat"
y = repmat(x,[m n]);
function y = f4(x,m,n) %// Luis' "dirty"
y(m,n) = 0;
y(:) = x;
function y = f5(x,m,n) %// Luis' "indexing"
y(1:m,1:n) = x;
function y = f6(x,m,n) %// Divakar's "matrix porod"
y = x*ones(m,1)*ones(1,n);
Benchmarking script for square arrays:
x = 3;
sizes = round(logspace(1,3.7,10)); %// max limited by computer memory
for s = 1:numel(sizes)
n = sizes(s);
m = sizes(s);
time_f1(s) = timeit(#() f1(x,m,n));
time_f2(s) = timeit(#() f2(x,m,n));
time_f3(s) = timeit(#() f3(x,m,n));
time_f4(s) = timeit(#() f4(x,m,n));
time_f5(s) = timeit(#() f5(x,m,n));
time_f6(s) = timeit(#() f6(x,m,n));
end
loglog(sizes, time_f1, 'r.-');
hold on
loglog(sizes, time_f2, 'g.:');
loglog(sizes, time_f3, 'b.-');
loglog(sizes, time_f4, 'm.-');
loglog(sizes, time_f5, 'c.:');
loglog(sizes, time_f6, 'k.:');
xlabel('Array size')
ylabel('Time')
legend('ones', 'zeros', 'repmat', 'dirty', 'indexing', 'matrix prod')
For column arrays: just change the following lines:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = 1;
m = sizes(s);
For row arrays:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = sizes(s);
m = 1;
Results for a dual-core CPU, 2-GB RAM, Windows Vista, Matlab R2010b:
Square arrays;
Column arrays;
Row arrays.
There are two basic ways to do this:
A = ones(10,1)*3
B = zeros(10,1)+3
The first one is most commonly used in examples, yet if I am not mistaken, the second one performs slightly better. All in all it is just a matter of taste.
Of course, if you have an existing matrix, there is another simple way:
C = zeros(10,1)
C(:) = 3;
And for completeness, the repmat solution as suggested by #Luis is also fine.
As an alternative, a matrix multiplication (which is supposed to be pretty fast on MATLAB) based method could be also be suggested for 2D or multidimensional array assignment work.
Thus, assuming m as rows, n as columns and x as the value to be assigned for all elements, the code would be -
y = x*ones(m,1)*ones(1,n);
I need to sort these values randomly in an array.
int [] d = new int[26];
d[0]=1;
d[1]=5;
d[2]=10;
d[3]=25;
d[4]=50;
d[5]=75;
d[6]=100;
d[7]=200;
d[8]=300;
d[9]=400;
d[10]=500;
d[11]=750;
d[12]=1000;
d[13]=2000;
d[14]=3000;
d[15]=4000;
d[16]=5000;
d[17]=7500;
d[18]=10000;
d[19]=25000;
d[20]=50000;
d[21]=100000;
d[22]=250000;
d[23]=500000;
d[24]=750000;
d[25]=1000000;
Assuming you are writing this in C++ you can use random_shuffle function template from the Standard library. http://www.cppreference.com/wiki/algorithm/random_shuffle
If you want to write your own function, simply take two random indices and swap their values. Put that in a loop and do it as many times as think necessary for the array to be well shuffled (I would say a number of times equal to two times the number of elements in the array).
In psudo-code (since you haven't indicated the language)
NUMBER_OF_SHUFFLES = 2;
for(ix = 0; ix < NUMBER_OF_SHUFFLES * myArray.length; ix++)
index1 = random(myArray.length)
index2 = random(myArray.length)
temp = index1
myArray[index1] = myArray[index2]
myArray[index2] = temp
There are more sophisticated ways of doing it as well. Check out this discussion: An Efficient way of randomizing an array - Shuffle code
If it's java you may use
Arrays.shuffle(d);