名称的结果与概率不符

时间:2019-07-13 19:37:24

标签: java

我正在尝试编写此程序,该程序随机选择3个名称 选择名称后,每次弹出该名称时,该名称再次出现的可能性都会降低10%。

问题是,当我将for循环中的所有名称更改为一个名称时,我将所有内容更改为90%的名称,而将另外2个名称之一更改为10%。

String [] arr = new String[30];

int i; int b; int g;

for (i = 0; i < 11; i++)
{
    arr[i] = "moshe";
}

for (b = 9; b < 20; b++)
{
    arr[b] = "Nir";
}

for (g = 22; g < 29; g++)
{
    arr[g] = "Yoad";
}

double letsdomath = Math.random()*arr.length; // Exp: return the no. 10 / 30 letsdomath = 10

if (letsdomath < 11) // if i get moshe
{
    for (i = 0; i <= letsdomath - 1; i++)
    {
        arr[i] = "Nir"; // Originally it would be Moshe here
        arr[i + 1] = "Nir";
    }
}

if (letsdomath > 11 && letsdomath < 21) // if i get nir
{
    for (b = 0; b <= letsdomath -1; b++)
    {
        arr[b] = "Nir";
        arr[b + 1] = "Nir"; // Originally it would be Yoad here
    }
}

if (letsdomath > 21 && letsdomath < 30) // if i get yoad
{
    for (g = 0; g <= letsdomath -1; g++)
    {
        arr[g] = "Nir"; // Originally it would be Yoad here
        arr[29] = "Nir"; // Originally it would be Moshe here
    }
}
System.out.println(arr[(int) letsdomath]);

预期结果:
要使名字Nir每次弹出

实际结果:
Nir的名称会弹出90%〜,Yoad的名称会弹出10%〜。

1 个答案:

答案 0 :(得分:1)

让我们重新回顾一下您想做的事情:为什么不将您所说的每件事实现为“我们可以做的事”,然后运行“尽可能多的迭代”,这些迭代只是按顺序进行?

例如,让我们从基础开始:

import java.util.*; 
import java.lang.Math;

public class Test  {
  String[] names;
  int len;
  double[] probabilities, thresholds;

  public static void main(String[] args) {
    new Test();
  }

  public Test() {
    init();
    int steps = 5;
    for (int i=0; i<steps; i++) {
      // do the thing!
    }
  }

  public void init() {
    // set up a probability distribution
    names = new String[]{"name1", "name2", "name3"};
    len = names.length;
    thresholds = new double[len];
    probabilities = new double[len];
    for (int i=0; i<len; i++) {
      probabilities[i] = 1./len;
    }
  }
}

然后,我们确保有一种方法来查找概率阈值:如果概率为[0.4,0.3,0.3],则我们需要阈值[0,0.4,0.7],以便我们可以轻松地处理以下事实:随机数> = 0但<0.4应该解析为索引0,数字> = 0.4但<0.7应该解析为索引1,依此类推:

// turns [0.3, 0.4, 0.3] into [0, 0.3, 0.7]
public void setThresholds() {
  double tally = 0;
  for (int i=0; i<len; i++){
      thresholds[i] = tally;
      tally += probabilities[i];
  }
}

然后,让我们根据选择的名称索引定义重新平衡概率的函数:

// turns [0.4, 0.3, 0.3] with pos=0 into [0.36, 0.32, 0.32]
public void updateProbabilities(int namePos) {
  double sprinkle = (probabilities[namePos] * 0.1) / (len - 1.);
  probabilities[namePos] *= 0.9;
  for (int i=0; i<len; i++) {
    if (i == namePos) continue;
    probabilities[i] += sprinkle;
  }
}

正确,完成所有设置后,我们现在就可以依靠这些功能按预期运行(当然应该验证),以更新public Test()以运行一百万次更新并通过一次: / p>

  public Test() {
    init();

    int steps = 5;

    for (int i=0; i<steps; i++) {
      setThresholds();
      double randomValue = Math.random();

      // find the associated name by finding the index of
      // the threshold that is higher than our random value.
      int namePos = findIndex(randomValue);
      if (namePos == -1) {
        namePos = names.length;
      }
      namePos--;

      updateProbabilities(namePos);

      // String name = names[namePos];
      // System.out.println("step " + i + ": picked " + name + " (index " + namePos + ") based on " + randomValue);
      // System.out.println("new probabilities: " + Arrays.toString(probabilities));
    }

    System.out.println("Final probabilities: " + Arrays.toString(probabilities));
  }

  public int findIndex(double randomValue) {
    for (int i=0; i<len; i++) {
      if (thresholds[i] > randomValue) return i;
    }
    return -1;
  }

注释掉那些中间控制台日志,因为您当然不想看到一千个中介...除非您这样做。