Jump to content

Module:ProbabilityFormat

From RiskiPedia

Template:Documentation

Purpose

This module provides functions to convert fractional probabilities (e.g. `0.01`) into human-friendly text strings such as:

  • `"no chance"`
  • `"100% chance"`
  • `"about 1 in 100"`
  • `"almost zero chance (less than 1 in 1,000,000)"`

It is designed for use in templates where probabilities need to be expressed in plain language.

Usage

Basic syntax:

{{#invoke:ProbabilityFormat|convert|probability|cutoff}}

  • probability (required) — a number between `0` and `1`.
  • cutoff (optional) — probabilities smaller than this are treated as “almost zero chance.” Defaults to `1e-6` (1 in 1,000,000).

Parameters

probability
The fractional probability, either as a number or string (e.g. `0.05`).
cutoff
A fractional cutoff for “almost zero” reporting. For example, passing `1e-4` will show “less than 1 in 10,000.”

Examples

Input Output
{{#invoke:ProbabilityFormat|convert|0}} no chance
{{#invoke:ProbabilityFormat|convert|1}} 100% chance
{{#invoke:ProbabilityFormat|convert|0.95}} almost certain (more than 9 in 10)
{{#invoke:ProbabilityFormat|convert|0.7}} about 7 in 10
{{#invoke:ProbabilityFormat|convert|0.01}} about 1 in 100
{{#invoke:ProbabilityFormat|convert|1e-8}} almost zero chance (less than 1 in 1,000,000)
{{#invoke:ProbabilityFormat|convert|1e-5|1e-4}} almost zero chance (less than 1 in 10,000)

See also



local p = {}

-- Format an integer with commas as thousands separators
local function format_with_commas(n)
    local s = tostring(n)
    local sign, int = s:match("^([%-]?)(%d+)$")
    int = int:reverse():gsub("(%d%d%d)", "%1,")
    int = int:reverse():gsub("^,", "")
    return sign .. int
end

-- Converts a fractional probability to a human-friendly "1 in X" string
-- @param frame.args[1] Probability in [0,1] (string or number)
-- @param frame.args[2] (optional) Cutoff for "almost zero chance"
-- @return A string like "1 in 100", "no chance", or "100% chance"
function p.convert(frame)
    --[[ Implementation details:
         - Handles 0 or negative as "no chance"
         - Handles >=1 as "100% chance"
         - Rounds reciprocal to one significant digit ]]
    local prob_str = frame.args[1]
    -- Check for valid input
    if prob_str == nil or prob_str == '' then
        return "Error: No probability provided"
    end
    local prob = tonumber(prob_str)
    if not prob then
        return "Error: Invalid probability"
    end

    local cutoff = tonumber(frame.args[2]) or 1e-6

    -- Handle special cases
    if prob <= 0 then
        return "no chance"
    elseif prob < cutoff then
        return "almost zero chance (less than 1 in "
            .. format_with_commas(math.floor(1 / cutoff)) .. ")"
    elseif prob >= 1 then
        return "100% chance"
    elseif prob >= 0.95 then
        return "almost certain (more than 9 in 10)"
    elseif prob >= 0.55 then
        -- Probabilities close to 1 (more than 1 in 2): Express as "6/7/8/9 in 10"
        local n = math.floor(prob*10 + 0.5)
        return "about " .. n .. " in 10"
    else
        -- Calculate and round to one significant digit
        local recip = 1 / prob
        local exponent = math.floor(math.log10(recip))
        local mantissa = recip / (10 ^ exponent)
        local rounded_mant = math.floor(mantissa + 0.5)
        local rounded = rounded_mant * (10 ^ exponent)
        return "about 1 in " .. format_with_commas(math.floor(rounded))
    end
end

return p