Java随机点名器(带权重的随机算法)

通过带权重的随机算法来实现随机点名器,该点名器的效果是点到的学生再次被点到的概率下降一半。

核心思想:给每个学生设置权重,初始权重全部为1.0,计算权重总和和学生实际的占比,然后在创建数组来模拟权重范围,例如:
arr = {1.0,2.0,3.0,4.0,5.0,6.0},那么如果随机数随机到3.14,则表示点到的学生位于3.0-4.0之间,在返回数组中3.14这个数应存入位置的索引来表示是第几个学生被点到了。
第一个同学范围:【0-1.0)
第二个同学范围:【1.0-2.0)
第三个同学范围:【2.0-3.0)...
以此类推,当同学被点到的之后修改同学对于的权重,修改为原来的一半即可。
/*
* 需求:
*       用程序实现随机点名器。
*       要求点到的学生再次被点到的概率下降一半
*       需要读取本地文件中的数据
*       数据格式:XXX-男-20-1.0
*       分别表示:姓名-性别-年龄-权重占比
* */
代码实现:
创建学生类:
package RamdomRollCaller;

public class Student {
    private String name;
    private String gender;
    private int age;
    private double weight;

    public Student() {

    }

    public Student(String name, String gender, int age, double weight) {
        this.name = name;
        this.gender = gender;
        this.age = age;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return name + "-" + gender + "-" + age + "-" + weight;
    }
}

完整代码实现:

package RamdomRollCaller;

import java.io.*;
import java.lang.reflect.AnnotatedArrayType;
import java.util.ArrayList;
import java.util.Arrays;

public class RollCallerDemo5 {
    /*
    * 需求:
    *       用程序实现随机点名器。
    *       要求点到的学生再次被点到的概率下降一半
    *       需要读取本地文件中的数据
    *       数据格式:XXX-男-20-1.0
    *       分别表示:姓名-性别-年龄-权重占比
    * */
    public static void main(String[] args) throws IOException {
        //关联本地文件
        BufferedReader br = new BufferedReader(new FileReader("b.txt"));
        //创建集合用于临时存储数据
        ArrayList<String> nameTempList = new ArrayList<>();
        //创建集合存储学生对象便于管理和操作
        ArrayList<Student> students = new ArrayList<>();
        //读数据
        String str = "";
        while ((str = br.readLine()) != null) {
            nameTempList.add(str);
        }
        //关流
        br.close();
        //获取数据内容并创建学生对象添加到集合
        for (String nameStr : nameTempList) {
            String[] arr = nameStr.split("-");
            students.add(new Student(arr[0], arr[1], Integer.parseInt(arr[2]), Double.parseDouble(arr[3])));
        }
        //计算总比重
        double weight = 0;
        for (Student student : students) {
            weight = weight + student.getWeight();
        }
        //计算每个人的实际占比
        double[] arr = new double[students.size()];
        int index = 0;
        for (Student student : students) {
            arr[index] = student.getWeight() / weight;
            index++;
        }
        //计算每个人的占比范围
        for (int i = 1; i < arr.length; i++) {
            arr[i] = arr[i] + arr[i - 1];
        }
        //制造0-1.0的随机数
        double random = Math.random();
        //二分查找,计算出随机数应存入的位置
        //细节:调用Arrays的二分查找方法,该方法返回负的索引值减一
        //     要得到最终索引需要反向操作,用返回值的相反数减一得到被点到的学生对象在students集合中的位置
        int i = -Arrays.binarySearch(arr, random) - 1;
        Student result = students.get(i);
        System.out.println(result.getName());
        //修改该学生的占比
        double w = result.getWeight() / 2;
        result.setWeight(w);
        //将修改后的数据写到源文件中
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
        for (Student s : students) {
            bw.write(s.toString());
            bw.newLine();
        }
        //关流
        bw.close();
    }
}

运行效果:

随机到的同学占比修改为0.5,再次运行程序:

在C#中,权重随机选择通常涉及到概率分布和随机数生成。一个常见的方法是使用`System.Collections.Generic.Dictionary<TKey, TValue>`或者`Dictionary<T, double>`来存储元素及其对应的权重,然后利用这些权重来计算每个元素被选中的概率。这里有一个简单的概念实现: ```csharp using System; using System.Collections.Generic; using System.Linq; class WeightedRandomSelection { private readonly Dictionary<int, double> weights; public WeightedRandomSelection(Dictionary<int, double> weights) { this.weights = weights; // 确保所有权重的和为1(或接近于1),以便进行正确的概率计算 double totalWeight = weights.Values.Sum(); if (totalWeight != 1) { weights = weights.ToDictionary(kvp => kvp.Key, kvp => kvp.Value / totalWeight); } } public int Choose() { double randomValue = Random.NextDouble(); // 0到1之间的随机浮点数 double cumulativeProbability = 0; foreach (var (key, weight) in weights) { cumulativeProbability += weight; if (randomValue <= cumulativeProbability) { return key; } } throw new InvalidOperationException("无法生成随机选择,可能是因为权重总和不为1"); } } public class Program { static void Main(string[] args) { Dictionary<int, double> selections = new Dictionary<int, double> { {1, 0.3}, {2, 0.4}, {3, 0.3} }; WeightedRandomSelection random = new WeightedRandomSelection(selections); int chosenNumber = random.Choose(); Console.WriteLine($"随机选择了数字: {chosenNumber}"); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值