Module:math

Hello, you have come here looking for the meaning of the word Module:math. In DICTIOUS you will not only get to know all the dictionary meanings for the word Module:math, but we will also tell you about its etymology, its characteristics and you will know how to say Module:math in singular and plural. Everything you need to know about the word Module:math you have here. The definition of the word Module:math will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofModule:math, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.

Various mathematical functions.

Detailed documentation

export.tonumber_extended

function export.tonumber_extended(x, base, finite_real, no_prefix)

An extended version of tonumber(), which attempts to convert x to a number. Like tonumber(), it will convert from base 10 by default, and the optional parameter base can be used to specify a different base between 2 and 36, with the letters A-Z (case-insensitive) representing additional digits beyond 0-9. When strings contain hexadecimal notation (e.g. "0x100"), base 16 is used as the default instead, but this is overridden if base is set to anything other than 16.

This function differs from tonumber() in the following ways:

  • If finite_real is set, then the function will only return finite real numbers; inputs which would normally produce ±infinity or NaN will instead produce nil.
  • If no_prefix is set, then strings which start with "0x" will not be interpreted as containing hexadecimal notation, resulting in nil.
  • If base is explicitly set to 10, then strings in hexadecimal notation will always return nil. This fixes a bug in tonumber(), which treats base=10 the same as base being unset, causing base 16 to be used if x contains hexadecimal notation (e.g. tonumber("0x10", 10) returns 16, whereas tonumber_extended("0x10", 10) returns nil).

export.to_integer

function export.to_integer(x)

Converts x to an integer by removing the fractional portion (e.g. 3.5 becomes 3, and -2.9 becomes -2). This is equivalent to rounding down positive numbers and rounding up negative numbers. If conversion is not possible, returns nil.

export.sign

function export.sign(x, signed_0)

Returns 1 if x is positive, -1 if x is negative, or 0 if x is 0.

If signed_0 is set, this function will only return either 1 or -1, and will make a distinction between signed zeroes (+0 and -0). This is useful when a 0 result could be disruptive (e.g. x % 0).

export.is_finite_real_number

function export.is_finite_real_number(x)

Returns true if x is a finite real number, or false if not.

export.is_integer

function export.is_integer(x)

Returns true if x is an integer, or false if not.

export.is_positive_integer

function export.is_positive_integer(x, include_0)

Returns true if x is a positive integer (or zero if the include_0 flag is set), or false if not.

export.is_NaN

function export.is_NaN(x)

Returns true is x is NaN (Not a Number), or false if not.

NaN is a value that has the type "number", but does not represent an actual numeric value; it has the unique property that if x is NaN, x ~= x evaluates to true.

export.log10

function export.log10(x)

Returns the base-10 logarithm of x.

This function should be used instead of math.log10, which is deprecated and may stop working if Scribunto is updated to a more recent Lua version.

export.to_hex

function export.to_hex(dec, include_prefix)

Converts a decimal number to hexadecimal. If include_prefix is set, the returned number will include the 0x prefix.

export.gcd

function export.gcd(x, ...)

Returns the greatest common divisor of an arbitrary number of input numbers.

export.lcm

function export.lcm(x, ...)

Returns the least common multiple of an arbitrary number of input numbers.


local export = {}

local byte = string.byte
local ceil = math.ceil
local floor = math.floor
local format = string.format
local is_integer -- defined below
local match = string.match
local select = select
local tonumber = tonumber
local tonumber_ext -- defined below
local tostring = tostring
local type = type

local INF = math.huge

local function sign(x, signed_0)
	if x > 0 then
		return 1
	elseif x < 0 then
		return -1
	elseif x == 0 then
		-- 1/(+0) is infinity and 1/(-0) is -infinity.
		return signed_0 and (1 / x > 0 and 1 or -1) or 0
	end
	-- NaN: convert to string with a forced sign prefix, and grab the first byte.
	local sign = byte(format("%+f", x))
	return sign == 0x2B and 1 or -- +
		sign == 0x2D and -1 or -- -
		-- If there's no sign, throw an error. This shouldn't be possible, but
		-- avoids silent errors if it does happen.
		error("Internal error: cannot determine sign of " .. x)
end

--[==[
An extended version of {tonumber()}, which attempts to convert `x` to a number. Like {tonumber()}, it will convert from base 10 by default, and the optional parameter `base` can be used to specify a different base between 2 and 36, with the letters {A-Z} (case-insensitive) representing additional digits beyond {0-9}. When strings contain hexadecimal notation (e.g. {"0x100"}), base 16 is used as the default instead, but this is overridden if `base` is set to anything other than 16.

This function differs from {tonumber()} in the following ways:
* If `finite_real` is set, then the function will only return finite real numbers; inputs which would normally produce ±infinity or NaN will instead produce {nil}.
* If `no_prefix` is set, then strings which start with {"0x"} will not be interpreted as containing hexadecimal notation, resulting in {nil}.
* If `base` is explicitly set to {10}, then strings in hexadecimal notation will always return {nil}. This fixes a bug in {tonumber()}, which treats {base=10} the same as {base} being unset, causing base 16 to be used if `x` contains hexadecimal notation (e.g. {tonumber("0x10", 10)} returns {16}, whereas {tonumber_extended("0x10", 10)} returns {nil}).]==]
function export.tonumber_extended(x, base, finite_real, no_prefix)
	-- TODO: tonumber() maxes out at 2^64 if the base is anything other than 10.
	-- TODO: support binary (0b) and octal (0o) prefixes.
	local n = tonumber(x, base)
	if not n or finite_real and (n ~= n or n == INF or n == -INF) then
		return nil
	-- If `base` is explicitly set to 10 (not simply nil), or `no_prefix` is set
	-- and `base` is nil or 16, filter out inputs that started with hexadecimal
	-- prefixes. Note that if `base` is anything else, the initial "0x" will
	-- have been interpreted as digits by tonumber() instead of a prefix (as "x"
	-- can be a digit from base 34 upwards), so there's no prefix to check for.
	elseif base == 10 or no_prefix and (base == nil or base == 16) then
		return not match(x, "^%s*?0()") and n or nil
	end
	return n
end
tonumber_ext = export.tonumber_extended

--[==[
Converts `x` to an integer by removing the fractional portion (e.g. {3.5} becomes {3}, and {-2.9} becomes {-2}). This is equivalent to rounding down positive numbers and rounding up negative numbers. If conversion is not possible, returns {nil}.]==]
function export.to_integer(x)
	x = tonumber(x)
	if not (x and x == x and x ~= INF and x ~= -INF) then
		return nil
	elseif x % 1 == 0 then
		return x
	-- Round-down positives.
	elseif x >= 0 then
		return floor(x)
	end
	--Round-up negatives.
	return ceil(x)
end

--[==[
Returns {1} if `x` is positive, {-1} if `x` is negative, or {0} if `x` is {0}.

If `signed_0` is set, this function will only return either {1} or {-1}, and will make a distinction between ] ({+0} and {-0}). This is useful when a {0} result could be disruptive (e.g. {x % 0}).]==]
function export.sign(x, signed_0)
	return sign(
		tonumber(x) or
		error(format("bad argument #1 to 'sign' (number expected, got %s)", type(x)), 2),
		signed_0
	)
end

--[==[
Returns {true} if `x` is a finite real number, or {false} if not.]==]
function export.is_finite_real_number(x)
	return x and x == x and not (x == INF or x == -INF) and type(x) == "number"
end

--[==[
Returns {true} if `x` is an integer, or {false} if not.]==]
function export.is_integer(x)
	return x and type(x) == "number" and x % 1 == 0 or false
end
is_integer = export.is_integer

--[==[
Returns {true} if `x` is a positive integer (or zero if the `include_0` flag is set), or {false} if not.]==]
function export.is_positive_integer(x, include_0)
	return x and type(x) == "number" and (x > 0 or include_0 and x == 0) and x % 1 == 0 or false
end

--[==[
Returns {true} is `x` is ] (Not a Number), or {false} if not.

NaN is a value that has the type "number", but does not represent an actual numeric value; it has the unique property that if {x} is NaN, {x ~= x} evaluates to {true}.]==]
function export.is_NaN(x)
	return x ~= x
end

--[==[
Returns the base-10 logarithm of `x`.

This function should be used instead of {math.log10}, which is deprecated and may stop working if Scribunto is updated to a more recent Lua version.]==]
function export.log10(x) -- Structured like this so that module documentation works.
	local log10 = math.log10
	if log10 ~= nil then
		return log10
	end
	local log = math.log
	return log(10, 10) == 1 and function(x) -- Lua 5.2
		return log(x, 10)
	end or function(x) -- Lua 5.1
		return log(x) * 0.43429448190325182765112891891660508229439700580367 -- log10(e)
	end
end
export.log10 = export.log10() -- Sets the actual returned function.

local function integer_error(x, param, func_name)
	local type_x = type(x)
	error(format(
		"bad argument #%d to '%s' (integer expected, got %s)",
		param, func_name, type_x == "number" and tostring(x) or type_x
	), 3)
end

--[==[
Converts a decimal number to hexadecimal. If `include_prefix` is set, the returned number will include the 0x prefix.]==]
function export.to_hex(dec, include_prefix)
	dec = tonumber(dec) or dec
	if not is_integer(dec) then
		integer_error(dec, 1, "to_hex")
	end
	local neg = dec < 0
	if neg then
		dec = -dec
	end
	-- Inputs >= 2^64 cause string.format to return "0".
	if dec >= 0x1p64 then
		error("integer overflow in 'to_hex': cannot convert inputs with a magnitude greater than or equal to 2^64 (18446744073709551616)", 2)
	end
	-- string.format treats hex numbers as unsigned, so any sign must be added manually.
	return format("%s%s%X", neg and "-" or "", include_prefix and "0x" or "", dec)
end

--[==[
Returns the greatest common divisor of an arbitrary number of input numbers.]==]
function export.gcd(x, ...)
	x = tonumber(x) or x
	if not is_integer(x) then
		integer_error(x, 1, "gcd")
	end
	local q, args_len, integers = ..., select("#", ...)
	-- Compute p_1 = gcd(n_1, n_2), p_2 = gcd(p_1, n_3), ... i.e. compute GCD by Euclid's algorithm for the current result and the next number.
	for i = 2, args_len + 1 do
		q = tonumber(q) or q
		if not is_integer(q) then
			integer_error(q, i, "gcd")
		elseif x ~= 1 then -- If x is 1, validate remaining inputs.
			-- GCD of two integers x, q with Euclid's algorithm.
			while q ~= 0 do
				x, q = q, x % q
			end
		end
		if i <= args_len then
			-- Only create a table if absolutely necessary, as it's inefficient.
			if i == 2 then
				integers = {...}
			end
			q = integers
		end
	end
	return x < 0 and -x or x
end

--[==[
Returns the least common multiple of an arbitrary number of input numbers.]==]
function export.lcm(x, ...)
	x = tonumber(x) or x
	if not is_integer(x) then
		integer_error(x, 1, "lcm")
	end
	local q, args_len, integers = ..., select("#", ...)
	-- Compute the product of all inputs as p and GCD as x.
	for i = 2, args_len + 1 do
		q = tonumber(q) or q
		if not is_integer(q) then
			integer_error(q, i, "lcm")
		elseif x ~= 0 then  -- If x is 0, validate remaining inputs.
			-- Compute the product.
			local p = x * q
			-- GCD of two integers x, q with Euclid's algorithm.
			while q ~= 0 do
				x, q = q, x % q
			end
			-- Divide product by the GCD to get new LCM.
			x = p / x
		end
		if i <= args_len then
			-- Only create a table if absolutely necessary, as it's inefficient.
			if i == 2 then
				integers = {...}
			end
			q = integers
		end
	end
	return x < 0 and -x or x
end

return export