如何处理Lua math.random异常

3

我需要在Lua代码中寻求一点帮助。想法是获取一个0-18之间的随机数,但不能是数字816。怎样实现呢?

self.currentSkyTexture = math.random(0,18)

-- 不是 8 或者 16,那么怎么办?
6个回答

4
制作一个回答表格。
local rans = {0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,17,18}

从表格中选择

function myRandom() return rans[math.random(#rans)] end

这会以均匀的概率从表格中选择一个条目,并为每个条目调用一次 math.random


列表中的双倍数15是故意的还是打错了? - greatwolf
@greatwolf,这是一个打字错误。 - Ben Grimm

2

由于在19个可能的随机数中只有2个例外,因此暴力方法不会导致性能问题。

function myRandom()
    local ret
    repeat
        ret = math.random(0,18)
    until ret ~= 8 and ret ~= 16
    return ret
end

self.currentSkyTexture = myRandom()

如果@WerewolF经常这样做随机操作,那么这是一种更优雅、DRY的解决方案。 - Alex Popov

2
在最简单的情况下,您可以通过直接检查来替换排除:
function skipRandom()
    local ret = math.random(0,16)
    if ret == 8 then 
        ret = 17 
    elseif ret == 16 then 
        ret = 18 
    end
    return ret
end

self.currentSkyTexture = skipRandom()

你觉得它为什么会比表查找运行得更快?你有对其他方案进行基准测试吗? - Doug Currie
不,但你让我对我的假设感到好奇。在lua-5.1中,我的速度比你快5%。在5.2中,你的速度比我快5%,而在luajit 2.0.3中,你的速度比我快8%。在所有情况下,对random的重复调用比输家慢10-15%。 - Ben Grimm
我在一台微型(Atom处理器)Debian Wheezy Lua 5.2.1上运行了一个微基准测试,这两种方法非常相似;对于1000万次迭代,skipRandom为0m8.138s;基于表格的myRandom为0m7.509s。 - Doug Currie

2

只需检查它是否为8或16,并重新运行随机操作,直到其为其中之一。


0

只是为了好玩,这将生成特定参数的排除数组和函数:

function makeExcludedRandom(min,max,exclude)
    local values = {}
    local i = 0
    local j = 0
    table.sort(exclude)
    while i < max-min-1 do
       while exclude[j+1] == min+i+j do
          j = j + 1
       end

       values[i+1]=min+i+j
       i=i+1
    end

    return function()
        return values[math.random(min,max)]
    end
end    
local skipRandom = makeExcludedRandom(0,18,{8,16})

self.currentSkyTexture = skipRandom()

0

简单的解决方案(如果使用少量数字,请使用第一个答案)。

function randomize()
    local r = math.random(0,18);
    if (r == 8 or r == 16) then 
        return randomize();
    end
    return r;
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接