如何在数组中生成一个比其他随机数多的随机数

本文关键字:随机数 一个 其他 数组 | 更新日期: 2023-09-27 18:09:56

我有一个数字列表,例如:{1,2,3,4,5,6} .

我想随机生成这些数字,我这样做:

void Update(){
    float ran = Random.Range(1,6);
    print(ran);
}

如何生成或打印比其他数字多的3 ?

如何在数组中生成一个比其他随机数多的随机数

如果您想要倾斜分布,您可以,比如说,将生成的值映射到所需的分布

// all 1..6 are equal with exception of 3 which appears more frequently 
// 1..2, 4..6 - 10% each (1 occurence  per 10 items)
// 3          - 50%      (5 occurences per 10 items)
private static int[] map = new int[1, 2, 3, 4, 5, 6, 3, 3, 3, 3];
...
void Update{
  float ran = map[Random.Range(map.Length)];
  print(ran);
}

设置threemulplier为1表示正态分布,2表示2个以上的3,3表示3个以上的3,依此类推

void Update() {
    int threeMultiplier = 2; // Twice as much 3's
    int maxNumber = 6;
    int num = Random.Range(1, threeMultiplier * maxNumber);
    if (num > maxNumber) num = 3;
    print(num); 
}

"掷骰子黑客"的一个解决方案可能是:

"convert ran to int"

switch (ran) 
 case 1: 
   return 1
 case 2: 
   return 2
 case 3:
   return 3
 case 4:
   return 4
 case 5: 
   return 5
 case 6:
   return 6
 default:
   return 3

所以你将有50%的机会3,10%的机会对方,减少3-s的数量改变10到较小的值^^

这里有一些解决方案,使用概率论,但它是过度工程。它也可以有轻微的语法错误,因为我现在远离visual studio (

)
var data = new float[] {1, 2, 3, 4, 5, 6};
var indexToWeight = (index) => {
  if (index == 3) return 2;
  return 1; 
};
var total = data.Select((value, index) => indexToWeight(index)).Sum(); 
var weightedData = data.Select((value, index) => Tuple.Create(value, indexToWeight(index)/(float)sum)).ToList();
var boundedData = new List<Tuple<float, float>>(weightedData.Count);
float bound = 0.0f;
for (int i = 0; i < weightedData.Count; i++) {
  boundedData.Add(Tuple.Create(weightedData[i].Item1, bound));
  bound += weightedData[i].Item2;
}
var weightedToValue = (List<Tuple<float, float>> wv, float p) => {
  var pair = wv.FirstOrDefault(item => item.Item2 > p);
  if (pair != null) return pair.Item1;
  return vw.Last().Item1; 
}; 
Random random;
var randomizedData = Enumerable.Range(1, data.Count).Select(index => weightedtoValue(weightedData, random.NextDouble())).ToArray();   

检查我在。net fiddle中做的这个例子。在这段代码中,你有两种可能性。我很确定这能解决你的问题,这是一个非常简单的解决方案。当然在Unity中你可能想使用Random.Range…修改一些变量的名字,等等等等。

1-你可以打印列表中有多少个元素就可以打印多少次,所以一个有'n'个元素的列表总是会输出'n'个数字。

2-你可以打印任何你想要的数量,只要你改变变量timesToPrint

代码将根据chanceToPrintGoldenNumber打印goldenNumber,否则将在列表中打印一个随机元素(可能是意外的黄金数字)。

示例链接在这里!

代码:

public static void Main()
{
    Random rnd = new Random();
    var li = new List<int> {1,2,5,3,6,8};
    var timesToPrint = 10;
    var goldenNumber = 3;
     // this is actually 55% chance, because we generate a number form 0 to 100 and if it is  > than 45 we print it... so 55% chance
    var chanceToPrintGoldenNumber = 45;

    // Print as many times as there are numbers on the list
    Console.WriteLine("Printing as many times as there are elements on the list");
    foreach(var number in li)
    {       
        var goldenNumberChance = rnd.Next(0,100);
        if (goldenNumberChance > chanceToPrintGoldenNumber) // 55% chance to print goldenNumber
        {
            Console.WriteLine(goldenNumber);            
        }
        else
        {           
            var i = rnd.Next(0,li.Count);
            Console.WriteLine(li[i]);           
        }
    }
    Console.WriteLine("****************** END ***************************");
    // Print as many times as the value of your "timesToPrint".
    Console.WriteLine("Printing as many times as the value on timesToPrint ");
    for(var i=0; i< timesToPrint; i++)
    {
        var goldenNumberChance = rnd.Next(0,100);
        if (goldenNumberChance > chanceToPrintGoldenNumber) // 55% chance to print goldenNumber
        {
            Console.WriteLine(goldenNumber);            
        }
        else
        {           
            var n = rnd.Next(0,li.Count);
            Console.WriteLine(li[n]);           
        }
    }
}

对于加权分布,我会这样做:

public class RandomGenerator
{
    Dictionary<Tuple<double, double>, Tuple<int, int>> probability;
    Random random;
    public RandomGenerator(Dictionary<double, Tuple<int, int>> weights)
    {
        random = new Random();
        Dictionary<double, Tuple<int, int>> percent = weights.Select(x => new { Key = x.Key / weights.Keys.Sum(), Value = x.Value }).ToDictionary(t => t.Key, t => t.Value);
        probability = new Dictionary<Tuple<double, double>, Tuple<int, int>>();
        double last = 0;
        foreach (var item in percent.OrderBy(x => x.Key).Select(x => new { Key = x.Key, Value = x.Value }))
        {
            probability.Add(new Tuple<double, double>(last, last + item.Key), item.Value);
            last += item.Key;
        }
    }
    public double GetRandomNumber()
    {
        double w = random.NextDouble();
        var range = probability.Where(x => w >= x.Key.Item1 && w <= x.Key.Item2).First().Value;
        return random.Next(range.Item1, range.Item2);
    }
}

你可以这样使用:

Dictionary<double, Tuple<int, int>> weights = new Dictionary<double, Tuple<int, int>>();
weights.Add(80, new Tuple<int, int>(1, 100));
weights.Add(20, new Tuple<int, int>(3,3));
var randgen = new RandomGenerator(weights);
var number = randgen.GetRandomNumber();