随机数求和在Matlab中的实现

kyxcudwk  于 2022-11-15  发布在  Matlab
关注(0)|答案(2)|浏览(356)

我有从第1行到第12行的数字列表,比方说在A列,我需要将每行的数字分布到四个不同的列(B、C、D、E列),以便:(I)B、C、D、E列中显示的值的总和等于A列的值。(Ii)这些值只能是整数。(Iii)B、C、D、E栏的最高限额分别为10、10、5及5。(Iv)B、C、D、E栏的最低限额分别为5、5、3、3。
也就是说,在这些列中生成的值应该包含在这些最大限制值中。
示例:|A|B|C|D
17|6|5|3|3
有没有办法从A列中选取值,然后得到不同列(B、C、D、E)中的值,从而使每一行的总和等于A?
我试过了,但还是找不到准确的目标。其中一些问题是在编码后提到的:

clear all
while true
 A=randi([3 5],12,4);
     if((sum(A,2)>=16) | (sum(A,2)<=30));
   break;
end
end

disp(A);
disp(sum(A,2));

所有生成的值都是随机的,但是它们介于16和30之间。但是最低限值我不能理清,BCDE怎么办?如果我已经有A列的数据,那么我如何才能使每行的BCDE值等于该总和?

ogsagwnx

ogsagwnx1#

快速、确定性的方法,无需使用循环。这个想法是首先将数字A一分为二,LRLR的条件都在[8 15]之间。函数randSplit(x, lo, hi)可以做到这一点。
选择L = B + DR = C + E。现在剩下的两个部分是将L拆分成[B, D],并将R拆分成[C, E];函数randSplit(x, lo, hi, LO, HI)将执行此操作。这种情况下的条件是BC都在[5 10]D之间,E都在[3 5]之间。
此方法速度很快,因为它在输出矩阵的每一行恰好调用randi 3次。

A = randi([16 30], 12,1);
mat = zeros(12,4);
for i = 1:12   
    [L, R] = randSplit(A(i), 8, 15); % L = B + D, R = C + E
    [B, D] = randSplit(L, 3, 5, 5, 10);
    [C, E] = randSplit(R, 3, 5, 5, 10);
    mat(i,:) = [B C D E];
end

function [a, b] = randSplit(x, lo, hi, LO, HI)
    if nargin == 3
        a = randi([max(lo,x-hi) min(hi,x-lo)]);
        b = x - a;
    elseif nargin == 5
        a = randi([max(LO,x-hi) min(HI,x-lo)]);
        b = x - a;
    end
end

示例输出:

[A mat] =
    29    10    10     5     4
    21     8     5     5     3
    23    10     5     5     3
    21     5     9     4     3
    17     5     6     3     3
    27     8     9     5     5
    19     8     5     3     3
    30    10    10     5     5
    17     5     6     3     3
    27    10     9     5     3
    18     5     6     3     4
    25     9    10     3     3
cczfrluj

cczfrluj2#

我建议您使用一个简单的循环来完成此操作:

M = [0,0,0,0];  % A, B, C, D
For each A
    While sum(M) is not A
        M(A) = [(2 random numbers 5-10), (2 random numbers 3-5)]
    end
end

使用randi获取随机数。
这对于大数字/列表来说并不是最优的,但我相当肯定对于您处理的数字来说已经足够快了,除非您这样做数百万次。
我将把在MatLab中实现这一点留给您作为练习。:)如果你被卡住了,大喊一声。

更新:

这是快速和肮脏的,但它的工作:)它平均使用130毫秒的tio.run。

A = 15+randi(15,12,1);
BCDE = zeros(numel(A),4);
temp = [0, 0, 0, 0];
for ii = 1:numel(A)
    temp = [4+randi(6,1,2), 2+randi(3,1,2)];
    while sum(temp) ~= A(ii)
        temp = [4+randi(6,1,2), 2+randi(3,1,2)];
    end
    BCDE(ii,:) = temp;
end
[A, BCDE]

ans = 
   16    5    5    3    3
   18    5    5    4    4
   18    5    6    4    3
   29   10   10    5    4
   24    6   10    3    5
   27   10    9    4    4
   18    5    6    3    4
   23    5   10    5    3
   27    9    8    5    5
   24    7    9    3    5
   28   10   10    3    5
   20    9    5    3    3

相关问题