【问题标题】:Selecting a number randomly with math.random()用 math.random() 随机选择一个数字
【发布时间】:2014-08-19 04:32:30
【问题描述】:

我想在一个范围内选择一个随机数,但是说生成的数字是“x”,下次我希望该数字至少为 x±20。我怎样才能做到这一点?

math.random()只带两个参数,所以如果轮到1,选择的数字是40,第二次应该是50或更多/30或更少,同样下次应该是60或更多/20或更少。

【问题讨论】:

  • "math.random() 只需要两个参数" 如果您告诉我们编程语言会有所帮助
  • @leonbloy:我正在使用 Lua,但 math.random() 是大多数编程语言(具有 1 或 2 个)参数中的函数
  • 假设参数是范围,我认为这更像是一种算法问题。语言应该无关紧要。
  • 你的意思是下一个数字应该在[x-20;x+20]之内,x是最后生成的数字?
  • 你能指定一个整体范围吗? (例如,仅使用 0 到 100 之间的数字)

标签: math random lua


【解决方案1】:

不了解 LUA,所以我们将使用伪代码

t = Math.random(0,60);
if (t > last_value - 20)
    t += 40
last_value = t

【讨论】:

  • 这可行,但与我的解决方案在两个方面有所不同:1:它允许小的“循环”距离(即,它允许 x[1]=1 x[2]=99)2:它确实not 给出 [0,100] 中的均匀分布。
【解决方案2】:

假设你想要一个在[0,L) 范围内的数字x,这样每个数字与前一个(在Java 中)的(循环)距离至少为d

  public static double rand1(double L, double d, double x) {
    double y = x +  d + Math.random() * (L - 2.0 * d) ;
    if (y >= L)
      y -= L;
    return y;
  }

禁止“周期性”小距离可能看起来是不必要的复杂化,但实际上是一种简化:一方面,这个简单的算法会在[0,L) 中产生均匀分布,而公认的答案不会。

【讨论】:

  • 我喜欢这个,因为它更通用——而且比我的回答更好:)
【解决方案3】:

如果您在 0 和 xMax 之间随机放置一个“主要”对象,并且必须将 1 个或多个“次要”对象放置在同一范围内,但距离 mainX 的主要对象至少 D,和次要对象可以尽可能靠近,如果有多个,那么试试这个:

function getRandPosNotTooCloseToMain(xMax, mainX, D)
    assert(2*D < xMax) -- if false then main too "fat"
    local leftLen = mainX - D
    local rightLen = xMax - (mainX + D)
    local leftSideWins = true -- need some default

    if leftLen < 0 then -- can only place it right side of main
        assert(rightLen > 0)
        leftSideWins = false

    elseif rightLen < 0 then -- can only place it on left side of main
        -- nothing to do, because leftSideWins already true

    else -- there is space on either side of main (both leftLen and rightLen > 0), 
         -- so randomly select one side then return random # on that side
        local ratio = leftLen / (leftLen + rightLen)
        if math.random() > ratio then -- right half wins
            leftSideWins = false
        else -- left side wins, this is the default
        end
    end

    if leftSideWins then 
        return math.random(0, leftLen)
    else
        return mainX + D + math.random(0, rightLen)
    end
end

这可以通过以下方式进行测试:

-- test
math.randomseed(os.time())
local numTests = 100000

-- generate a bunch of values for right side always wins: 
for x=1,numTests do 
    local x = getRandPosNotTooCloseToMain(60, 15, 20)
    assert( x >= 15+20, x ) 
end

-- generate a bunch of values for left side always wins: 
for x=1,numTests do 
    local x = getRandPosNotTooCloseToMain(60, 45, 20)
    assert( x <= 45-20, x ) 
end

-- generate a bunch of values for left side always wins: 
for x=1,numTests do 
    local x = getRandPosNotTooCloseToMain(60, 30, 20)
    assert( x <= 10 or x>= 50, x ) 
end

-- if get this far then all tests passed!
print("Passed!")

所有测试都通过。在您的情况下,您将通过math.random(0,xMax) 随机设置mainX

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 1970-01-01
    • 2014-04-30
    • 2010-12-10
    • 2019-07-27
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多