Asked by Hyunjae Jeon
on 16 Apr 2019

Hello,

I am trying to create a 20x24 matrix with each individual column containing random integers without duplicate.

(I just made this number but the size will become bigger)

So far, I could make a 20x1 column named "randomcolumn" containing random numbers by using following codes.

random=randperm(20,20);

randomcolumn=random.';

I am stuck with making this to run with for loop function so that individual columns will add up 24 times.

n=24;

for i=1:n

randomcolumn

end

Any help will be very appreciated. Thank you

Answer by KSSV
on 16 Apr 2019

Accepted Answer

iwant = zeros(20,24) ;

for i = 1:24

iwant(:,i) = randperm(20,20);

end

Answer by Stephen Cobeldick
on 16 Apr 2019

Edited by Stephen Cobeldick
on 16 Apr 2019

You do not need a loop, here is a much simpler solution in just one line:

>> [~,M] = sort(rand(20,24),1)

M =

16 20 17 10 15 10 13 6 16 13 11 18 12 16 4 17 20 4 1 7 8 12 16 14

10 10 19 14 12 7 1 11 12 16 2 5 8 15 15 14 17 3 19 6 19 2 13 17

20 12 10 8 14 19 14 12 20 9 19 9 1 10 9 9 6 17 10 12 17 20 7 11

17 8 9 5 3 12 18 19 2 17 8 2 11 8 12 2 16 16 15 11 1 18 8 12

4 5 16 7 2 6 2 10 17 14 17 19 10 3 18 16 11 13 7 2 16 6 20 9

3 11 3 20 4 13 12 5 8 11 14 6 3 13 16 3 4 7 12 14 7 5 11 20

15 9 13 2 8 17 16 17 19 7 7 7 9 19 2 4 15 2 13 1 10 9 2 18

11 17 20 9 11 18 6 20 4 8 5 12 18 1 5 8 5 6 14 8 18 15 9 16

5 6 7 4 20 14 5 15 9 3 4 17 15 2 7 18 2 19 8 18 9 14 4 2

6 19 11 15 13 9 7 16 15 12 1 14 6 9 13 11 8 9 3 4 11 8 6 13

12 16 2 17 18 16 15 4 7 4 10 3 17 14 14 7 7 18 6 17 4 16 12 6

14 3 1 13 6 5 4 7 11 15 20 13 19 17 19 1 18 11 11 13 14 7 14 8

19 15 14 11 10 20 3 1 6 10 15 20 14 7 11 12 12 14 17 9 2 11 5 15

1 14 6 3 5 8 19 13 10 18 6 8 16 6 8 20 9 1 16 16 3 17 17 4

8 2 12 19 7 1 8 8 1 1 16 15 7 4 20 5 19 8 5 10 5 3 10 10

18 7 15 12 16 2 20 9 14 20 3 10 2 12 1 15 1 15 18 19 15 10 1 1

2 18 5 6 19 15 9 18 13 19 9 4 20 20 10 13 3 20 20 15 12 19 19 5

9 4 4 18 9 4 17 2 18 2 13 16 4 11 17 19 13 10 9 5 13 13 18 7

13 1 18 1 17 11 10 3 3 5 18 1 5 5 3 6 14 12 2 20 20 1 3 19

7 13 8 16 1 3 11 14 5 6 12 11 13 18 6 10 10 5 4 3 6 4 15 3

Jan
on 17 Apr 2019

@Stephen: Simpler, but flawed. Modern randperm implementations use the efficient and not flawed Fisher-Yates-Shuffle (also called Knuth-Shuffle), while sorting random numbers has the (tiny) problem, that Matlab's sorting is stable, so if rand replies 2 equal numbers, their order is kept. rand can reply 2^53 different numbers, and the probability to get 2 equal elements is:

m = 2^53;

n = 20;

P = 1 - (m * (m-1) * . . . * (m-n+1)) / m^n

% See: birthday paradoxon

It is tiny, but not vanishing.

Stephen Cobeldick
on 17 Apr 2019

"...so if rand replies 2 equal numbers.."

I would be interested to know what is the actual probabilty of that occuring, to know exactly how "tiny" it is. Would a numeric calculation be robust enough?

According to the randperm documentation "randperm uses the same random number generator as rand, randi, and randn": if they use the same random number generator, why are there more different numbers available for randperm ? Given that they use the same random number generator, the only way randperm could be more random than sort(rand(..)) is if it detected identical values and called that random number generator again for them, repeating until no duplicate values exist. Is this documented somewhere?

Jan
on 17 Apr 2019

@Stephen: I've posted the function to determine the probability in my comment already.

randperm was a simple sort(rand()) call in older Matlab versions. To obtain much more speed and to avoid the mentioned problem, I've implemented the Fisher-Yates shuffle: FEX: Shuffle as C-Mex function. One of the implementations in Matlab:

for i = 2:numel(X) % Shuffle in forward direction:

w = ceil(rand * i); % 1 <= w <= i

t = X(w);

X(w) = X(i);

X(i) = t;

end

See https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle. Although this algorithm uses the same pseudo random number generators as randperm, it does not suffer from the problem of equal numbers and the stable sorting.

Note that this is biased also: ceil(rand * i) is not perfectly equally distributed: rand replies values equally distributed in (0,1) with 53 bit resolution. If this range is multiplied by 2, 3, 4, 5, ... you get different numbers of elements for the different integers. Better (if MathWorks has implemented randi carfully!):

w = randi([1, i]);

See the "modulo bias" on the Wikipedia page.

By the way, randi is massivly slower than rand. Actually the RNGs provide random 32 bit numbers. Picking the required bits and avoiding the modulo problem should not be more work that obtaining 2 random uint32 values and apply a multiplication to get a double.

Notes: The algorithms of rand, randi and randperm are not documented in public. I've sent an enhancement request to let randperm(n) run with the same speed as randperm(n,n).

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.