簡體   English   中英

嗨,我想使用math.random設置重復的可能性

[英]Hi I want to use math.random to set the likely for it to repeat

我想制作一個將生成隨機數的程序。 我知道我需要為此使用Math.random(),但我想為可重復的數字設置比率。 例如,我希望編譯器給出一個從1到10的數字,但我希望5重復一個比另一個數字大3倍的數字。 我怎么做? 請幫忙謝謝。

對於這種情況:

private static final int[] CHOICES = new int[] { 1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9, 10 };
public static int strangeRandom() {
    return CHOICES[ThreadLocalRandom.current().nextInt(CHOICES.length)];
}

從給定的一組選擇中隨機選擇,然后控制這些選擇,以便更有可能選擇5種。

這將使5個數字至少是其他9個數字的3倍:

private static int getRandom ()
{
    Random r = new Random();

    int next = r.nextInt(100000) + 1;

    if (next <= 25000)
    {
        return 5;
    }
    else
    {
        return r.nextInt(10) + 1;
    }
}

注意 :在其他情況下,也可以排除5,以嘗試更好地達到“ 3次”的可能性。 我不是為了簡單。

另一個變化 :這是一個使用nextInt()模數而不是25000/100000分割的變化。 另外,我將代碼放在其他情況下,嘗試排除5(沒有無限循環)。

private static int getRandom ()
{
    Random r = new Random();

    int next = r.nextInt();

    if (next % 4 == 0)
    {
        return 5;
    }
    else
    {
        int p = r.nextInt(10) + 1;
        int tries = 0;

        // try to not get a 5 for a few times
        while (p == 5 && tries++ < 4)
        {
            p = r.nextInt(10) + 1;
        }
        return p;
    }
}

測試代碼

public static void main(String[] args)
{       
    Map<Integer, Integer> frequecnyMap = new HashMap<Integer, Integer>();

    for (int i = 0; i < 12000; i++)
    {
        int r = getRandom();

        Integer n = frequecnyMap.get(r);

        if (n == null)
        {
            frequecnyMap.put(r, 1);
        }
        else
        {
            frequecnyMap.put(r, n + 1);
        }
    }
    System.out.println(frequecnyMap);
}

樣本輸出(第二變化)

{1 = 971,2 = 975,3 = 995,4 = 1037,5 = 3025,6 = 1042,7 = 995,8 = 976,9 = 969,10 = 1015}

{1 = 1016、2 = 1019、3 = 994、4 = 968、5 = 3068、6 = 1030、7 = 996、8 = 914、9 = 990、10 = 1005}

{1 = 939,2 = 944,3 = 979,4 = 986,5 = 3023,6 = 1040,7 = 1007,8 = 1046,9 = 997,10 = 1039}

首先,您應該使用Random類,而不是Math.random() 例如,它具有一個不錯的輔助方法nextInt(int n) ,該方法生成介於0和n-1(含)之間的隨機整數。

在您的特定情況下,您需要一個1-10的數字,因此生成0-9並加1,即nextInt(10) + 1

但是,您希望數字5出現3次的頻率更高。 一種快速的骯臟方法是生成兩個額外的數字(1-12)並將它們映射到5。

Random rnd = new Random();
int num = rnd.nextInt(12) + 1;
if (num == 11 || num == 12)
    num = 5;

就像我說的那樣,既快捷又骯臟,但這確實適合您的特定情況。


現在,對於更通用的解決方案,您希望能夠指定加權概率。 數字1-4、6-10的權重為1,數字5的權重為3。

然后,您要做的是對權重求和(12),並生成一個隨機數,然后找到累加權重超過該隨機數的數字。

這是一種方法:

private static int random(Random rnd, int ... weights) {
    if (weights.length < 2)
        throw new IllegalArgumentException("Need at least two weights");
    int total = 0;
    for (int weight : weights) {
        if (weight <= 0)
            throw new IllegalArgumentException("Invalid weight: " + weight);
        if ((total += weight) < 0)
            throw new IllegalArgumentException("Weight overflow");
    }
    for (int i = 0, val = rnd.nextInt(total); ; i++, val -= weights[i])
        if (val < weights[i])
            return i;
}

然后可以這樣稱呼它:

Random rnd = new Random();
int num = random(rnd, 1,1,1,1,3,1,1,1,1,1) + 1;

注意+1 ,因為該方法類似於Random.nextInt(n)並且將數字0返回到n-1,其中n是給定的權重數。

您可以輕松地將其變成一個不錯的類,在該類上權重由構造函數指定,並且該類為您管理Random對象。

請注意,隨着權重增加,性能會下降。 有一種方法可以使用TreeMapbinarySearch進行改進,但是您需要類的實現,以便它可以准備數據。

如果要完全控制隨機生成的數字,則應執行以下操作:

public class MyRandom {
    private int[] probability;
    private long[] ntimes;
    private long times;

    public MyRandom(int[] probability) {
        this.probability = new int[10];
        System.arraycopy(probability, 0, this.probability, 0, probability.length);
        ntimes=new long[10];
        for(int i=0; i < ntimes.length; i++)
            ntimes[i]=0;
        times=0;
    }

    public void showProbability() {
        for (long i : probability) {
            System.out.print(i+" ");
        }
        System.out.println();
    }

    public int random() {
        int t = 10;

        int r = (int)Math.floor(Math.random()*10+1);
        double p = 0;
        if (times == 0) 
            p = 0;
        else
            p = ntimes[r-1]*100/times;

        System.out.println("P: "+p +" : "+probability[r-1]);
        while (p > probability[r-1] && t > 0) {
            r = (int)Math.floor(Math.random()*10+1);
            p = ntimes[r-1]*100/times;            
            t--;
        }
        ntimes[r-1]++;
        times++;
        return r;
    }

    public long getOcurrences(int i) {
        return ntimes[i-1];
    }


    //This is an example of how to use it.        
    public static void main(String[] args) {
        int[] p = {5, 5, 5, 5, 30, 5, 5, 5, 10, 15};
        MyRandom mr = new MyRandom(p);

        for (int i = 0; i < 2000; i++) {
            int r = mr.random();
            System.out.println("Id: "+i+" Number: "+r+" Ocurrences: "+mr.getOcurrences(r));
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM