【问题标题】:How to generate two random integers such that their running sums have a given ratio如何生成两个随机整数,使它们的运行总和具有给定的比率
【发布时间】:2019-07-24 13:58:29
【问题描述】:

我正在尝试生成两个随机整数,每个整数都有自己的潜在值范围。我保留了每个值的运行总和,并且需要确保这些总和之间的比率保持在给定值的范围内。

对于每次试验,我希望两个数字都是随机的。 IE。我不想生成一个值,然后计算另一个值来获得我想要的比率。

我发现的最佳解决方案是针对每次试验,只生成随机数对,直到随机数对符合我的约束条件。但是它不能保证找到解决方案,并且可能会循环很长时间。

import random

XMIN, XMAX = 64, 2500
YMIN, YMAX = 16, 2000
GOAL, THRESH =0.90, 0.03

def trial(sumX, sumY):
  x,y=0,0
  while True:
    x = random.randint(XMIN,XMAX)
    y = random.randint(YMIN,YMAX)
    if abs( (sumX+x)/(sumX+x+sumY+y)-GOAL) <= THRESH:
      return x,y


sumX,sumY=0,0
for I in range(10000):
  x,y=trial(sumX,sumY)
  trial_ratio = x/(x+y)

  sumX, sumY = sumX+x, sumY+y
  sum_ratio = sumX/(sumX+sumY)
  print(f"+({x:5d}, {y:5d}) = {trial_ratio:0.2%}      :     ({sumX:8d}, {sumY:8d})  = {sum_ratio:0.2%}")

sn-p是python的,语言无所谓

上述工作按预期工作,但是如果可能的话,我希望能够更快地终止,而不是仅仅进行随机猜测并抛出无效结果。

【问题讨论】:

  • 如果在生成之前为每个随机数计算一个新的可接受范围(基于之前的数字),就不会有“抛出无效结果”的问题。
  • (XMAX-XMIN) 和 (YMAX - YMIN) 有多大
  • @GauravMathur 这些值是任意的(用户可选择),但 sn-p 顶部的值不会异常。 GOAL 和 THRESH 在 0 和 1 之间确实是任意的。
  • @RobertHarvey 这不会导致允许的范围收敛到一个值吗?此时这些值不再是随机的。
  • 我想它会产生与丢弃结果相同的效果,直到你得到一个在范围内的结果,除了它会更快。

标签: random


【解决方案1】:

一种可能的解决方案是预先计算所有可能的组合并创建一个配对列表。然后立即从该列表中选择任意数量的随机项目。

var validData = new List<(int, int)>();
for (int i = XMIN; i <= XMAX; i++)
{
    for (int j = YMIN; j <= YMAX; j++)
    {
        var isValid = true;//logic to verify if it is valid
        if (isValid)
            validData.Add((i, j));
    }
 }

然后您可以简单地从validData 列表中选择随机对。

var index = rand.Next(validData.Count);
var pair = validData[index];

此解决方案将保证您总能找到一对随机配对。

对不起,代码是用 C# 编写的,我还不懂 Python :)

【讨论】:

  • 谢谢,高拉夫。我认为这在技术上可行,但它的缩放比例为 O(n^2),因此在大范围内,我认为这可能会比随机选择更糟糕。
  • 是的,这就是为什么我问这些数字有多大:)
【解决方案2】:

使用 RobertHarvey 的提示,我能够计算出每次试验的 x 和 y 的可能范围。

我之前曾假设这样做会导致可能的范围收敛,这样我将不断获得xy 的相同值。

首先我通过假设YMINYMAX 被选为y 来计算x 有效范围的绝对极值。然后我从该范围内随机选择 x。最后,在给定选定的x 的情况下,我重新计算y 的极值,并从该范围内选择y

def clamp(val, min_val,max_val):
  return int(max(min_val, min(val, max_val)))

def trial2(sumX, sumY):
  _xmin = -sumX - ((GOAL - THRESH)*(YMIN + sumY))/(-1 + GOAL - THRESH)
  _xmax = -sumX - ((GOAL + THRESH)*(YMAX + sumY))/(-1 + GOAL + THRESH)

  xmin = clamp(_xmin,  XMIN,XMAX)
  xmax = clamp(_xmax,  XMIN,XMAX)
  x = random.randint(xmin,xmax)

  _ymin = ((-THRESH-GOAL+1)*(x+sumX) + (-THRESH-GOAL)*sumY)/(GOAL+THRESH)
  _ymax = (( THRESH-GOAL+1)*(x+sumX) +  (THRESH-GOAL)*sumY)/(GOAL-THRESH)
  ymin = clamp(_ymin,  YMIN,YMAX)
  ymax = clamp(_ymax,  YMIN,YMAX)
  y = random.randint(ymin, ymax)


  return x, y

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-04
    • 2012-02-11
    • 1970-01-01
    • 2014-03-01
    • 2013-06-04
    • 1970-01-01
    相关资源
    最近更新 更多