算法-使用randn()实现randm()的套路

如何利用一个randn()【表示得到从1到n的随机数】改造为一个randm()的函数?

rand()函数要求的是每个位置出现等概率。

首先会想到使用 乘 + if判断的解法,以rand3实现rand7为例:

while(true) {
    int s = rand3() * 3 - 2; //因为原数至少为2,所以不满足条件,需要减掉2
    return s;
}

乍一看,确实只会返回1到7的整数,

但是假设原来rand3()获取每个位置的概率是1/3,这现在获取1的概率必须要三次都取得1,即(1/3)^3

而要取得4【即三个整数和为6】,可以是2 2 2,也可以是1 2 3的任何一种排列(共6种),即取得4的概率是取得1概率的7倍,这显然不符合每个位置取得概率相同的定义。

解题方法

(1)将srand = rand3() - 1,使得变成0, 1, 2随机取;

(2)将srand 扩大到刚好容纳一个rand3() - 1的程度,即扩大三倍

(3)将srand * 3 + rand3() - 1

(4)筛选结果,若在0 ~ 6中, + 1返回;否则再来一次

public int rand3_To_rand7() {
        while (true) {
            int srand = (rand3() - 1) * 3;
            int sum = srand + rand3() - 1;
            if (sum >= 7) { //模板:保證每個7都出現相同的概率,即8,9的存在會使得1,2概率上升。
                continue;
            } else {
                return sum + 1; //對七取余会导致得不到7,需要整体右移一位
            }
        }
    }

分析:

将srand扩大三倍,会随机生成0 3 6这三个数,每个未知的空位刚好为3(空位需要带上自己)

对其随机加上0 1 2,就会使得出现res: 0 1 2 3 4 5 6 7 8的概率相等

当res >= 7时,说明超过了0 ~ 6 七个数的范围,剔除。

返回res + 1


对于其他复杂一点的情况,只需适当求余即可,如rand5()实现rand7():

 public int rand5_To_rand7(){
        while (true) {
            int srand = rand5() - 1;
            int s = srand * 5;
            int sum = s + rand5() - 1;
            if (sum >= 21) {
                continue;
            } else {
                return sum % 7 + 1;
            }
        }
    }

总结:

关键步骤是扩大间隙,要扩大到刚好可以装得下n - 1个数的位置即可。

在返回时,确定范围必须满足所求随机数的最大值的整数倍,使得取得每个位置概率相等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-means算法是一种无监督学习算法,用于聚类分析。以下是使用matlab实现k-means算法的步骤: 1.初始化k个质心(centroid),可以随机选择k个样本作为质心。 2.对于每个样本,计算其与k个质心的距离,将其归为距离最近的质心所在的簇(cluster)中。 3.对于每个簇,重新计算其质心的位置,即取簇中所有样本的均值作为新的质心位置。 4.重复步骤2和3,直到质心位置不再改变或者达到预设的迭代次数。 下面是使用matlab代码实现k-means算法的示例: ```matlab % 生成示例数据 data = [randn(100,2)+1; randn(100,2)-1]; % 初始化质心 k = 2; centroids = datasample(data,k,'Replace',false); % 迭代计算 maxIter = 10; for i = 1:maxIter % 计算距离并分类 dist = pdist2(data, centroids); [~, cluster] = min(dist,[],2); % 计算新的质心位置 for j = 1:k centroids(j,:) = mean(data(cluster==j,:)); end end % 可视化结果 scatter(data(:,1),data(:,2),[],cluster); hold on; scatter(centroids(:,1),centroids(:,2),'rx','LineWidth',2); ``` 在上面的示例中,我们生成了一个包含两个簇的示例数据,然后使用k=2进行聚类分析。在迭代计算过程中,我们计算样本点与质心的距离,并将其归为距离最近的质心所在的簇中。然后,根据每个簇中的所有样本计算新的质心位置,并将其作为下一次迭代的起点。最后,我们将聚类结果可视化出来,其中蓝色和红色分别表示两个簇和质心位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值