Modul:FormatNum: Ferqa di neqeba guhartoyan de

8110 bayt hatine jêbirin ,  20 kanûna paşîn
kurteya guhartinê tune ye
(Rûpela nû: "--2013-06-16 FormatNum * format * round FormatNum() local FormatNum = { }; -- Constant for round method "round half to even" (IEEE 754). local ROUND_TO_EVEN = 0; -- Const...")
 
No edit summary
 
-- This module is intended to replace the functionality of Template:Formatnum and related templates.
--[[ 2013-06-16
local p = {}
FormatNum
* format
* round
FormatNum()
]]
local FormatNum = { };
 
function p.main(frame)
local args = frame:getParent().args
local prec = args.prec or ''
local sep = args.sep or ''
local number = args[1] or args.number or ''
local lang = args[2] or args.lang or ''
-- validate the language parameter within MediaWiki's caller frame
if lang == "arabic-indic" then -- only for back-compatibility ("arabic-indic" is not a SupportedLanguage)
lang = "fa" -- better support than "ks"
elseif lang == '' or not mw.language.isSupportedLanguage(lang) then
-- Note that 'SupportedLanguages' are not necessarily 'BuiltinValidCodes', and so they are not necessarily
-- 'KnownLanguages' (with a language name defined at least in the default localisation of the local wiki).
-- But they all are ValidLanguageCodes (suitable as Wiki subpages or identifiers: no slash, colon, HTML tags, or entities)
-- In addition, they do not contain any capital letter in order to be unique in page titles (restriction inexistant in BCP47),
-- but they may violate the standard format of BCP47 language tags for specific needs in MediaWiki.
-- Empty/unspecified and unsupported languages are treated here in Commons using the user's language,
-- instead of the local 'ContentLanguage' of the Wiki.
lang = frame:callParserFunction( "int", "lang" ) -- get user's chosen language
end
return p.formatNum(number, lang, prec, sep ~= '')
end
 
local digit = { -- substitution of decimal digits for languages not supported by mw.language:formatNum() in core Lua libraries for MediaWiki
["ml-old"] = { '൦', '൧', '൨', '൩', '൪', '൫', '൬', '൭', '൮', '൯' },
["mn"] = { '᠐', '᠑', '᠒', '᠓', '᠔', '᠕', '᠖', '᠗', '᠘', '᠙'},
["ta"] = { '௦', '௧', '௨', '௩', '௪', '௫', '௬', '௭', '௮', '௯'},
["te"] = { '౦', '౧', '౨', '౩', '౪', '౫', '౬', '౭', '౮', '౯'},
["th"] = { '๐', '๑', '๒', '๓', '๔', '๕', '๖', '๗', '๘', '๙'}
}
 
function p.formatNum(number, lang, prec, compact)
-- Constant for round method "round half to even" (IEEE 754).
local ROUND_TO_EVEN = 0;
 
-- Do not alter the specified value when it is not a valid number, return it as is
-- Constant for round method "round half away from zero"
local value = tonumber(number)
-- (German: "kaufmaennisches Runden"),
if value == nil then
-- also filters "-0" and converts it to "0".
return number
local ROUND_AWAY_FROM_ZERO = 1;
end
-- Basic ASCII-only formatting (without paddings)
number = tostring(value)
 
-- Check the presence of an exponent (incorrectly managed in mw.language:FormatNum() and even forgotten due to an internal bug, e.g. in Hindi)
-- Table storing the format options.
local exponent
local FORMAT_TABLE = {};
local pos = string.find(number, '[Ee]')
 
if pos ~= nil then
-- Format table for "de".
exponent = string.sub(number, pos + 1, string.len(number))
FORMAT_TABLE.de = {};
number = string.sub(number, 1, pos - 1)
FORMAT_TABLE.de.decimalMark = ",";
else
FORMAT_TABLE.de.groupMark = " ";
exponent = ''
FORMAT_TABLE.de.groupMinLength = 5;
end
FORMAT_TABLE.de.groupOnlyIntegerPart = false;
 
-- Format table for "de_currency".
FORMAT_TABLE.de_currency = {};
FORMAT_TABLE.de_currency.decimalMark = ",";
FORMAT_TABLE.de_currency.groupMark = ".";
FORMAT_TABLE.de_currency.groupMinLength = 5;
FORMAT_TABLE.de_currency.groupOnlyIntegerPart = true;
 
-- Format table for "ch".
FORMAT_TABLE.ch = {};
FORMAT_TABLE.ch.decimalMark = ",";
FORMAT_TABLE.ch.groupMark = "'";
FORMAT_TABLE.ch.groupMinLength = 5;
FORMAT_TABLE.ch.groupOnlyIntegerPart = true;
 
-- Format table for "en".
FORMAT_TABLE.en = {};
FORMAT_TABLE.en.decimalMark = ".";
FORMAT_TABLE.en.groupMark = ",";
FORMAT_TABLE.en.groupMinLength = 4;
FORMAT_TABLE.en.groupOnlyIntegerPart = true;
 
-- Format table for "iso31_0" (ISO 31-0 using comma as decimal mark).
FORMAT_TABLE.iso31_0 = {};
FORMAT_TABLE.iso31_0.decimalMark = ",";
FORMAT_TABLE.iso31_0.groupMark = " ";
FORMAT_TABLE.iso31_0.groupMinLength = 4;
FORMAT_TABLE.iso31_0.groupOnlyIntegerPart = false;
 
-- Format table for "iso31_0_point" (ISO 31-0 using point as decimal mark).
FORMAT_TABLE.iso31_0_point = {};
FORMAT_TABLE.iso31_0_point.decimalMark = ".";
FORMAT_TABLE.iso31_0_point.groupMark = " ";
FORMAT_TABLE.iso31_0_point.groupMinLength = 4;
FORMAT_TABLE.iso31_0_point.groupOnlyIntegerPart = false;
 
-- Format table for "pc" (simply nil to prevent formatting).
FORMAT_TABLE.pc = nil;
 
-- Format table for "comma" (no grouping - groupMark "").
FORMAT_TABLE.comma = {};
FORMAT_TABLE.comma.decimalMark = ",";
FORMAT_TABLE.comma.groupMark = "";
FORMAT_TABLE.comma.groupMinLength = 1000; -- (for performance, but also small values wouldn't matter)
FORMAT_TABLE.comma.groupOnlyIntegerPart = true;
 
-- Format table for "at" (only for convenience, same as "iso31_0").
FORMAT_TABLE.at = FORMAT_TABLE.iso31_0;
 
-- Format table for "ch_currency" (only for convenience, same as "de_currency").
FORMAT_TABLE.ch_currency = FORMAT_TABLE.de_currency;
 
-- Format table for "dewiki" (only for convenience, same as "de_currency").
FORMAT_TABLE.dewiki = FORMAT_TABLE.de_currency;
 
-- Constant defining digit group lenghts when digit grouping is used.
local DIGIT_GROUPING_SIZE = 3;
 
 
 
--[[
Internal used function for rounding.
 
@param a_number : Number to be rounded.
@param a_precision : Number of significant digits of the fractional part. If it
is negative, the according number of digits of the integer part are also
rounded.
@param a_roundMethod : Numeric constant defining the round method to use.
Supported are ROUND_TO_EVEN and ROUND_AWAY_FROM_ZERO.
 
-- Check the minimum precision requested
@return String of the rounded number like returned by Lua function string.format().
prec = tonumber(prec) -- nil if not specified as a true number
]]
if prec ~= nil then
local function numberToString(a_number, a_precision, a_roundMethod)
prec = math.floor(prec)
if (a_precision < 0) then
a_precisionif =prec -a_precision;< 0 then
prec = nil -- discard an incorrect precision (not a positive integer)
if (a_roundMethod == ROUND_TO_EVEN) then
elseif prec > 14 then
local integerPart = math.floor(math.abs(a_number) / (10 ^ a_precision));
ifprec (integerPart= %14 2-- ==maximum 0)precision thensupported by tostring(number)
-- next even number smaller than a_number / 10^precision
a_number = a_number - 5 * (10 ^ (a_precision - 1));
a_number = math.ceil(a_number / (10 ^ a_precision)) * (10 ^ a_precision);
else
-- next even number bigger than a_number / 10^precision
a_number = a_number + 5 * (10 ^ (a_precision - 1));
a_number = math.floor(a_number / (10 ^ a_precision)) * (10 ^ a_precision);
end
elseif (a_roundMethod == ROUND_AWAY_FROM_ZERO) then
if (a_number >= 0) then
a_number = a_number + 5 * (10 ^ (a_precision - 1));
a_number = math.floor(a_number / (10 ^ a_precision)) * (10 ^ a_precision);
else
a_number = a_number - 5 * (10 ^ (a_precision - 1));
a_number = math.ceil(a_number / (10 ^ a_precision)) * (10 ^ a_precision);
end
end
-- handle it as normal integer
a_precision = 0;
end
 
if (a_roundMethod == ROUND_AWAY_FROM_ZERO) then
-- Preprocess the minimum precision in the ASCII string
if ((a_number * (10 ^ a_precision)) - math.floor(a_number * (10 ^ a_precision)) == 0.5) then
local dot
-- because string.format() uses round to even, we have to add (numbers >0) or
if (prec or 0) > 0 then
-- subtract (numbers <0) a little bit to point into the "correct" rounding
pos = string.find(number, '.', 1, true) -- plain search, no regexp
-- direction if a_number is exactly in the middle between two rounded numbers
if (a_numberpos >~= 0)nil then
prec = pos + prec - string.len(number) -- effective number of trailing decimals to add or remove
a_number = a_number + (10 ^ -(a_precision + 1));
elsedot = '' -- already present
a_number = a_number - (10 ^ -(a_precision + 1));
end
else
ifdot (math= '.abs(a_number' *-- (10must ^ a_precision)) < 0.5)be thenadded
-- filter "-0" and convert it to 0
a_number = math.abs(a_number);
end
end
else
dot = '' -- don't add dot
prec = 0 -- don't alter the precision
end
return string.format("%." .. tostring(a_precision) .. "f", a_number);
end -- numberToString()
 
if lang ~= nil and mw.language.isKnownLanguageTag(lang) == true then
 
-- Convert number to localized digits, decimal separator, and group separators
 
local language = mw.getLanguage(lang)
--[[
if compact then
Internal used function for formatting.
number = language:formatNum(tonumber(number), { noCommafy = 'y' }) -- caveat: can load localized resources for up to 20 languages
 
else
@param a_number : String of a non-negative number to be formatted.
number = language:formatNum(tonumber(number)) -- caveat: can load localized resources for up to 20 languages
@param a_decimalMark : String of the decimal mark to use.
@param a_groupMark : String of the mark used for digit grouping.
@param a_groupMinLength : Number defining the minimum length of integer part
to use digit grouping (normally 4 or 5). However if fractional part is
longer than DIGIT_GROUPING_SIZE (3 as default) and digit grouping of
fractional part is not disabled via 'a_groupOnlyIntegerPart', then this
value is ignored and set to DIGIT_GROUPING_SIZE + 1.
@param a_groupOnlyIntegerPart : Boolean defining whether activating digit
grouping only for integer part (true) or for integer and fractional part
(false).
 
@return String of the formatted number according to the parameters.
]]
local function formatNumber(a_number, a_decimalMark, a_groupMark, a_groupMinLength, a_groupOnlyIntegerPart)
-- find the decimal point
local decimalPosition = mw.ustring.find(a_number, ".", 1, true);
local needsGrouping = false;
if (not decimalPosition) then
-- no decimal point - integer number
decimalPosition = mw.ustring.len(a_number) + 1;
if (decimalPosition > a_groupMinLength) then
needsGrouping = true;
end
-- Postprocessing the precision
else
--if decimalprec point> present0 then
local zero = language:formatNum(0)
if ((decimalPosition > a_groupMinLength) or (((mw.ustring.len(a_number) - decimalPosition) > DIGIT_GROUPING_SIZE) and (not a_groupOnlyIntegerPart))) then
needsGroupingnumber = true;number .. dot .. mw.ustring.rep(zero, prec)
elseif prec < 0 then
-- TODO: rounding of last decimal; here only truncate decimals in excess
number = mw.ustring.sub(number, 1, mw.ustring.len(number) + prec)
end
 
-- replace the decimal point
-- Append the localized base-10 exponent without grouping separators (there's no reliable way to detect a localized leading symbol 'E')
a_number = mw.ustring.sub(a_number, 1, decimalPosition - 1) .. a_decimalMark .. mw.ustring.sub(a_number, decimalPosition + 1);
if exponent ~= '' then
end
number = number .. 'E' .. language:formatNum(tonumber(exponent),{noCommafy=true})
if (needsGrouping and (decimalPosition > DIGIT_GROUPING_SIZE + 1)) then
-- grouping of integer part necessary
local i = decimalPosition - DIGIT_GROUPING_SIZE;
while (i > 1) do
-- group the integer part
a_number = mw.ustring.sub(a_number, 1, i - 1) .. a_groupMark .. mw.ustring.sub(a_number, i);
decimalPosition = decimalPosition + mw.ustring.len(a_groupMark);
i = i - DIGIT_GROUPING_SIZE;
end
else -- not localized, ASCII only
end
-- Postprocessing the precision
-- skip to the end of the new decimal mark (in case it is more than one char)
if prec > 0 then
decimalPosition = decimalPosition + mw.ustring.len(a_decimalMark) - 1;
number = number .. dot .. mw.string.rep('0', prec)
if (a_groupOnlyIntegerPart) then
needsGroupingelseif =prec false;< 0 then
-- TODO: rounding of last decimal; here only truncate decimals in excess
end
number = mw.string.sub(number, 1, mw.string.len(number) + prec)
if (needsGrouping and ((mw.ustring.len(a_number) - decimalPosition) > DIGIT_GROUPING_SIZE)) then
-- grouping of fractional part necessary
-- using negative numbers (index from the end of the string)
local i = decimalPosition - mw.ustring.len(a_number) + DIGIT_GROUPING_SIZE;
while (i <= -1) do
-- group the fractional part
a_number = mw.ustring.sub(a_number, 1, i - 1) .. a_groupMark .. mw.ustring.sub(a_number, i);
i = i + DIGIT_GROUPING_SIZE;
end
end
return a_number;
end -- formatNumber()
 
-- Append the base-10 exponent
 
if exponent ~= '' then
 
number = number .. 'E' .. exponent
--[[
Formatting numbers.
 
@param source : String representation
of an unformatted (but maybe rounded) floating point or integer number.
@param spec : Formatting option. Currently there are
"at", "comma", "de", "dewiki", "de_currency", "ch", "ch_currency", "en", "iso31_0",
"iso31_0_point" and "pc" supported. See the FORMAT_TABLE for details.
 
@return String of the formatted number.
If the argument 'spec' is invalid
or 'source' is not a valid string representation of a number,
'source' is returned unmodified.
]]
function FormatNum.format(source, spec)
local number;
if type(source) == "string" then
number = mw.text.trim(source);
end
if not spec or spec == "" then
spec = "dewiki"
end
if (number and spec) then
local format = FORMAT_TABLE[spec];
if (format) then
-- format entry found
local sign = mw.ustring.sub(number, 1, 1);
if ((sign == "+") or (sign == "-")) then
-- remove sign from number, add it later again
number = mw.ustring.sub(number, 2);
else
-- was not a sign
sign = "";
end
if (mw.ustring.sub(number, 1, 1) == ".") then
-- number begins with "." -> add a 0 to the beginning
number = "0" .. number;
else
if (mw.ustring.sub(number, -1) == ".") then
-- number ends with "." -> remove it
number = mw.ustring.sub(number, 1, -2);
end
end
if ((number == mw.ustring.match(number, "^%d+$")) or (number == mw.ustring.match(number, "^%d+%.%d+$"))) then
-- number has valid format (only digits or digits.digits) -> format it and add sign (if any) again
number = sign .. formatNumber(number, format.decimalMark, format.groupMark, format.groupMinLength, format.groupOnlyIntegerPart);
else
-- number has no valid format -> undo all modifications
number = source;
end
end
end
return number;
end -- FormatNum.format()
 
-- Special cases for substitution of ASCII digits (missing support in Lua core libraries for some languages)
 
if digit[lang] then
 
for i, v in ipairs(digit[lang]) do
--[[
number = mw.ustring.gsub(number, tostring(i - 1), v)
Rounding numbers.
end
 
@param number : string with unformatted floating point or integer number.
@param precision : number of significant fractional part digits.
If precision is negative, the integer part is rounded as well.
@param method : number defining the rounding method to use.
Currently are supported only
0 for 'IEEE 754' rounding and
1 for 'round half away from zero'.
If another number is supplied, the result is undefined.
 
@return String of the rounded number as returned by Lua function string.format().
If one of the arguments is not a number, 'number' is returned unmodified.
]]
function FormatNum.round(source, precision, method)
local number = tonumber(source);
if (number and precision and method) then
return numberToString(number, math.floor(precision), math.floor(method));
end
return source;
end -- FormatNum.round()
 
return number
 
 
local p = { };
 
function p.format(frame)
-- @param 1 : unformatted (but maybe rounded) floating point or integer number.
-- @param number : same as 1 (DEPRECATED, backward compatibility).
-- @param format : Formatting option. Currently there are
-- "at", "comma", "de", "dewiki", "de_currency", "ch", "ch_currency",
-- "en", "iso31_0", "iso31_0_point" and "pc" supported.
local source = frame.args[1];
if (not source) then
source = frame.args.number; -- DEPRECATED
pcall( require, "Module:FormatNumDEPRECATED" )
end
return FormatNum.format(source, frame.args.format) or "";
end -- .format()
 
 
 
function p.round(frame)
-- @param 1 : string with unformatted floating point or integer number.
-- @param number : same as 1 (DEPRECATED, backward compatibility).
-- @param precision : number of significant fractional part digits.
-- If precision is negative, the integer part is rounded as well.
-- @param method : number defining the rounding method to be used.
-- Currently are supported only
-- 0 for 'IEEE 754' rounding and
-- 1 for 'round half away from zero'.
-- If another number is supplied, the result is undefined.
local precision = tonumber(frame.args.precision);
local method = tonumber(frame.args.method);
local source = frame.args[1];
if (not source) then
source = frame.args.number; -- DEPRECATED
pcall( require, "Module:FormatNumDEPRECATED" )
end
if (source and precision) then
return FormatNum.round(source, precision, method);
end
return source or "";
end -- .round()
 
 
 
-- Export access for Lua modules
function p.FormatNum()
return FormatNum;
end -- .FormatNum()
 
 
-- DEPRECATED
function p.formatNumber(frame)
pcall( require, "Module:FormatNumDEPRECATED" )
return p.format(frame);
end
function p.numberToString(frame)
pcall( require, "Module:FormatNumDEPRECATED" )
return p.round(frame);
end
 
return p;
8600

guhartin