mic_none

Module:Sandbox/isaacl/Probability Source: en.wikipedia.org/wiki/Module:Sandbox/isaacl/Probability

local me = { }


-- quick and dirty implementation for test purposes

local fRandomSeedSet = false;

local function setRandomSeed()
    if not fRandomSeedSet then
        math.randomseed(os.time()+os.clock()*2^16+mw.site.stats.edits*2^16)
        fRandomSeedSet = true;
    end
end

--[[
Scales up Math.random() by F, so returns a random value in the range [0, F).
]]

function me.randomFloat(F)
    setRandomSeed()
    return F*math.random()
end  -- function me.randomFloat()

--[[
Returns an integer from 0 to M-1.
Uses the following algorithm in order to support values of M > the maximum value supported
by Math.random(upper):

Given a range [0, M): divide it into T partitions, with T-1 partitions of size N, and
the last partition holding the rest. Thus T = ceiling(M/N).

Partition 0 range:   [0, N)
Partition 1 range:   [N, 2N)
  ...
Partition T-1 range: [(T-1)*N, M)

Select a partition s = floor(math.random() * M / N)

If s is within range [0, T-2]: result = s*N + floor(me.randomFloat(N))
If s == T-1:                   result = s*N + floor(me.randomFloat(M-(T-1)*N))

--]]

local defaultPartitionSize = 2^31-1

-- optional parameter: partitionSize
function me.randomInt(M, partitionSize)
    setRandomSeed()
    local N = defaultPartitionSize
    if partitionSize ~= nil then
        N = partitionSize
    end
    -- optimization: if M < partition size N, then no need
    -- to partition the output range
    if M < N then
        return math.floor(me.randomFloat(M))
    end
    local T = math.ceil(M/N)
    local s = math.floor(math.random() * M / N)

    local result

    if s ~= (T-1) then
        result = s * N + math.floor(me.randomFloat(N))
    else
        result = s * N + math.floor(me.randomFloat(M-(T-1)*N))
    end

    return result
end  -- function me.randomInt()

return me