Diferencia entre revisiones de «Módulo:Math»

De Hispanopedia
Sin resumen de edición
Sin resumen de edición
Línea 269: Línea 269:
     local sign;
     local sign;
      
      
     -- Usa correctamente menos signos unicode en lugar de ASCII por defecto
     -- utiliza el signo de menos unario apropiado antes que el ASCII por defecto
     if value < 0 then
     if value < 0 then
         sign = '−';
         sign = '−';
Línea 313: Línea 313:
     -- Añadir notación exponencial, si es necesario
     -- Añadir notación exponencial, si es necesario
     if order ~= 0 then
     if order ~= 0 then
         -- Use proper unary minus sign rather than ASCII default
         -- Utiliza el signo de menos unario apropiado antes que el ASCII por defecto
         if order < 0 then
         if order < 0 then
             order = '−' .. lang:formatNum( math.abs(order) );
             order = '−' .. lang:formatNum( math.abs(order) );
Línea 327: Línea 327:


--[[
--[[
Helper function that interprets the input numerically.  If the
input does not appear to be a number, attempts evaluating it as
a parser functions expression.
Función de ayuda que interpreta la entrada numérica.  
Función de ayuda que interpreta la entrada numérica.  
Si la entrada no es un número, lo intenta evaluar como
Si la entrada no es un número, lo intenta evaluar como

Revisión del 15:58 4 abr 2013

Uso

Este módulo proporciona operaciones matemáticas básicas.

De momento, se utiliza solo la notación con punto decimal. Los parámetros de entrada deberían convertirse con {{formatnum:<num>|R}} y los valores devueltos se pueden formatear de nuevo con {{formatnum: <num>}}.

Funciones

random

Devuelve un número pseudoaleatorios. Sintaxis:

{{#Invoke:math|random}}

Sin ningún argumento, genera un número real en el rango [0,1) (con el 1 excluido), por ejemplo 0.27327761751287

{{#Invoke:math|random|<número>}}

Proporcionando un número entero, genera un número entero en el rango [1, número]. Si es negativo, el rango será [número, -1].

{{#Invoke:math|random|<primero>|<último>}}

Proporcionando dos números enteros, genera un número entero en el rango [primero, último].

Limitaciones: si se invoca más de una vez en la misma página entonces devolverá el mismo valor, aunque diferente cuando se refresque la página.

max

Encuentra el valor máximo de los argumentos. Sintaxis:

{{#Invoke:math|max|<valor 1>|<valor 2>|...}}
{{#Invoke:math|max}}

Cuando se usa sin argumentos, toma la entrada del marco superior. Cualquier valor numérico no válido es ignorado.

min

Encuentra el valor mínimo de los argumentos. Sintaxis:

{{#Invoke:math|min|<valor 1>|<valor 2>|...}}
{{#Invoke:math|min}}

Cuando se usa sin argumentos, toma la entrada del marco superior. Cualquier valor numérico no válido es ignorado.

cuenta

Cuenta el número de argumentos. Sintaxis:

{{#Invoke:math|cuenta|<valor 1>|<valor 2>|...}}
{{#Invoke:math|cuenta}}

Cuando se usa sin argumentos, toma la entrada del marco superior.

suma

suma los argumentos.

order

Determina el orden de magnitud de un número. Sintaxis:

{{#Invoke:math|order|<número>}}
{{#Invoke:math|order|x = <número>}}

Por ejemplo: 100 → 2, 0001 → -3

precision

Determina la precisión de un número. Sintaxis:

{{#Invoke:math|precision|<número>}}
{{#Invoke:math| precision| x = <número>}}

Es el inverso del orden de magnitud: indica el número de cifras decimales, incluidos ceros a la derecha, y una precisión negativa indica la potencia de 10 de la primera cifra significativa.

round

Redondea un número con una precisión determinada. Sintaxis:

{{#Invoke:math|round|<valor>|<precisión>}}
{{#Invoke:math|round|value = <valor>|precision = <precisión>}}

La precisión indica el número de cifras decimales. Una precisión negativa indica el múltiplo de la potencia de 10.

precision_format

Redondea un número con una precisión determinada y devuelve el valor en el formato numérico local o en notación científica cuando hace falta. Sintaxis:

{{#Invoke:math|precision_format|<número>|<precisión>}}

El número se puede expresar con la notación por ejemplo 4E9 y cuando el valor devuelto tiene un orden de magnitud de 9 o superior se expresa por ejemplo 4 × 10 9

_cleanNumber

Función auxiliar que evalúa si una entrada es numérica o si la puede convertir. Devuelve el valor numérico y el valor cadena. Puede ser útil en otros módulos.


--[[

Este módulo proporciona una serie de operaciones matemáticas básicas.

]]
local z = {}

-- Generar número aleatorio
function z.random(frame)
    local first = tonumber(frame.args[1])
    local second = tonumber(frame.args[2])
    local seed = tonumber(frame.args.seed)
    if seed then
        math.randomseed(seed * os.time())    -- inicialización pseudoaleatoria
    end
    if first and second then
        if first < second then
            return math.random(first,second)    -- entero entre [first,second]
        else
            return math.random(second,first)
        end
    elseif first then
        if first > 0 then
            return math.random(first)    -- entero entre [1,first]
        else
            return math.random(first,-1)
        end
    else
        return math.random()    -- número real entre [0,1)
    end
end

--[[
order

Determinar  el orden y la magnitud de los números

Usage:
    {{#invoke: Math | order | value }}
]]
function z.order(frame)
    local input_string = (frame.args[1] or frame.args.x or '0');
    local input_number;
    
    input_number = z._cleanNumber( frame, input_string );
    if input_number == nil then
        return '<strong class="error"><small>Error de formato: El orden de magnitud debe ser numérico</small></strong>'
    else
        return z._order( input_number )
    end    
end
function z._order(x)
    if x == 0 then return 0 end
    return math.floor(math.log10(math.abs(x)))
end

--[[
precision

Deteminar la precisión de un número usando la representación de cadena

Usage:
    {{ #invoke: Math | precision | value }}
]]
function z.precision( frame )
    local input_string = (frame.args[1] or frame.args.x or '0');
    local trap_fraction = frame.args.check_fraction or false;
    local input_number;
    
    if type( trap_fraction ) == 'string' then
        trap_fraction = trap_fraction:lower();
        if trap_fraction == 'false' or trap_fraction == '0' or
                trap_fraction == 'no' or trap_fraction == '' then
            trap_fraction = false;
        else
            trap_fraction = true;
        end
    end
    
    if trap_fraction then
        local pos = string.find( input_string, '/', 1, true );
        if pos ~= nil then
            if string.find( input_string, '/', pos + 1, true ) == nil then
                local denominator = string.sub( input_string, pos+1, -1 );
                local denom_value = tonumber( denominator );
                if denom_value ~= nil then
                    return math.log10(denom_value);
                end
            end                        
        end
    end    
    
    input_number, input_string = z._cleanNumber( frame, input_string );
    if input_string == nil then
        return '<strong class="error"><small>Error de formato: El valor de precisión ha de ser numérico</small></strong>'
    else
        return z._precision( input_string )
    end    
end
function z._precision( x )    
    x = string.upper( x )

    local decimal = string.find( x, '.', 1, true )
    local exponent_pos = string.find( x, 'E', 1, true )
    local result = 0;
    
    if exponent_pos ~= nil then
        local exponent = string.sub( x, exponent_pos + 1 )
        x = string.sub( x, 1, exponent_pos - 1 )
        result = result - tonumber( exponent )
    end    
    
    if decimal ~= nil then
        result = result + string.len( x ) - decimal
        return result
    end
        
    local pos = string.len( x );
    while x:byte(pos) == string.byte('0') do
        pos = pos - 1
        result = result - 1
        if pos <= 0 then
            return 0
        end
    end
    
    return result
end

--[[
max

Busca el argumento máximo

Utilizando:
    {{#invoke:Math| max | value1 | value2 | ... }}
o
    {{#invoke:Math| max }}

Cuando se utiliza sin argumentos, toma su entrada del marco superior. 
Tenga en cuenta que todos los valores que no se evalúan como números son ignorados.
]]
function z.max( frame )
    local args = frame.args;
    
    if args[1] == nil then
        local parent = frame:getParent();
        args = parent.args;
    end
    local max_value = nil;
    
    local i = 1;
    while args[i] ~= nil do
        local val = z._cleanNumber( frame, args[i] );
        if val ~= nil then
            if max_value == nil or val > max_value then
                max_value = val;
            end
        end        
        i = i + 1;
    end
  
    return max_value
end

--[[
min 

Buscar el argumento mínimo

Usando:
    {{#invoke:Math| min | value1 | value2 | ... }}
o
    {{#invoke:Math| min }}

Cuando se utiliza sin argumentos, toma su entrada del marco superior. 
Tenga en cuenta que todos los valores que no se evalúan como números son ignorados
]]
function z.min( frame )
    local args = frame.args;
    
    if args[1] == nil then
        local parent = frame:getParent();
        args = parent.args;
    end
    local min_value = nil;
    
    local i = 1;
    while args[i] ~= nil do
        local val = z._cleanNumber( frame, args[i] );
        if val ~= nil then
            if min_value == nil or val < min_value then
                min_value = val;
            end
        end        
        i = i + 1;
    end
  
    return min_value
end

--[[
round

Redondea un número a la precisión especificada

Usando:
    {{#invoke:Math | round | value | precision }}
    
--]]
function z.round(frame)
    local value, precision;
    
    value = z._cleanNumber( frame, frame.args[1] or frame.args.value or 0 );
    precision = z._cleanNumber( frame, frame.args[2] or frame.args.precision or 0 );
    
    if value == nil or precision == nil then
        return '<strong class="error">Error de formato: Los valores han de ser numéricos</strong>'
    else
        return z._round( value, precision );
    end    
end
function z._round( value, precision )
    local rescale = math.pow( 10, precision );
    return math.floor( value * rescale + 0.5 ) / rescale;
end

--[[
precision_format

Redondea un número a la precisión especificada y le da formato de acuerdo con las normas
originalmente utilizado para {{Plantilla: Rnd}}. La salida es una cadena.
Usage:
    {{#invoke: Math | precision_format | number | precision }}
]]
function z.precision_format( frame )
    -- Para acceder a Mediawiki incorporado formateador.
    local lang = mw.getContentLanguage();
    
    local value_string, value, precision;
    value, value_string = z._cleanNumber( frame, frame.args[1] or 0 );
    precision = z._cleanNumber( frame, frame.args[2] or 0 );
    
    -- Comprueba una entrada no numérica
    if value == nil or precision == nil then
        return '<strong class="error"><small>Error de formato: Datos no válidos para redondear</small></strong>'
    end
    
    local current_precision = z._precision( value );

    local order = z._order( value );
    
    -- Debido a los efectos de redondeo, es necesario limitar la precisión devuelta bajo
    -- algunas circunstancias debido a que sobre los dígitos terminales se informó incorrectamente.
    if order + precision >= 14 then
        orig_precision = z._precision( value_string );
        if order + orig_precision >= 14 then
            precision = 13 - order;        
        end        
    end

    -- Si el redondeo, trunca dígitos adicionales
    if precision < current_precision then
        value = z._round( value, precision );
        current_precision = z._precision( value );
    end    
    
    local formatted_num = lang:formatNum( math.abs(value) );
    local sign;
    
    -- utiliza el signo de menos unario apropiado antes que el ASCII por defecto
    if value < 0 then
        sign = '−';
    else
        sign = '';
    end    
        
    -- Manejar los casos que requieren la notación científica
    if string.find( formatted_num, 'E', 1, true ) ~= nil or math.abs(order) >= 9 then
        value = value * math.pow( 10, -order );
        current_precision = current_precision + order;
        precision = precision + order;
        formatted_num = lang:formatNum( math.abs(value) );
    else
        order = 0;        
    end
    formatted_num = sign .. formatted_num;
    
    -- Pad con ceros si es necesario    
    if current_precision < precision then
        local padding;
        if current_precision <= 0 then
            if precision > 0 then
                local zero_sep = lang:formatNum( 1.1 );
                formatted_num = formatted_num .. zero_sep:sub(2,2);

                padding = precision;
                if padding > 20 then
                    padding = 20;
                end
                
                formatted_num = formatted_num .. string.rep( '0', padding );
            end            
        else                   
            padding = precision - current_precision
            if padding > 20 then
                padding = 20;
            end
            formatted_num = formatted_num .. string.rep( '0', padding );
        end
    end

    -- Añadir notación exponencial, si es necesario
    if order ~= 0 then
        -- Utiliza el signo de menos unario apropiado antes que el ASCII por defecto
        if order < 0 then
            order = '−' .. lang:formatNum( math.abs(order) );
        else
            order = lang:formatNum( order );
        end    
        
        formatted_num = formatted_num .. '<span style="margin:0 .15em 0 .25em">×</span>10<sup>' .. order .. '</sup>'
    end
    
    return formatted_num;
end

--[[
Función de ayuda que interpreta la entrada numérica. 
Si la entrada no es un número, lo intenta evaluar como
un parser function.
]]

function z._cleanNumber( frame, number_string )
    if number_string == nil or number_string:len() == 0 then
        return nil, nil;
    end    
    
    -- Intento de conversión básico
    local number = tonumber( number_string )
    
    -- Si falla, trate de evaluar entrada como expresión
    if number == nil then        
        local attempt = frame:preprocess( '{{#expr: ' .. number_string .. '}}' );
        attempt = tonumber( attempt );
        if attempt ~= nil then
            number = attempt;
            number_string = tostring( number );
        else
            number = nil;
            number_string = nil;
        end
    else
    -- La cadena es válida pero puede contener relleno, límpiela.
        number_string = number_string:match( "^%s*(.-)%s*$" );
    end
    
    return number, number_string;
end

return z