sirve - JavaScript%(módulo) da un resultado negativo para números negativos
para que sirve el math abs (12)
Operación Modulo JavaScript
La implementación exitosa de un cálculo o algoritmo científico es posible no solo mediante la comprensión de las características que ofrece un lenguaje o marco en particular, sino también la comprensión de las limitaciones.
Las computadoras son instrumentos científicos precisos, pero funcionan al manipular entidades en espacios discretos (tiene un número limitado de píxeles en la pantalla, hay un número limitado de bits detrás de cada número, etc.)
Intente ignorar las limitaciones o las especificaciones del marco y pronto descubrirá que tiene una discrepancia de impedancia entre su fórmula matemática y el código que intenta escribir.
Operador modulo
A veces, las situaciones se complican con funciones de marco u operadores falsamente anunciados o comprendidos. Este artículo se centra en el módulo de operador.
Pregunte a cualquier programador de C # o JavaScript cuál es el operador de módulo en su idioma y existe una gran posibilidad de que contesten:% (por ejemplo, el signo de porcentaje). Mucha documentación se refiere al signo% como operador de módulo.
¡Guauu! Este es un error sutil pero muy peligroso. En C # y JavaScript, el operador se usa realmente para calcular el resto (con signo) que queda cuando un operando se divide por el segundo operando. Por lo tanto, se debe hacer referencia correctamente al operando como el operador del resto firmado.
A primera vista, el operador de resto firmado funciona de manera similar al operador de módulo. Hagamos algunas pruebas comparando los resultados devueltos por JavaScript con los devueltos por Google.
En Chrome, abra la consola (presione F12 y seleccione la pestaña Consola). Escriba allí, uno por uno, los cálculos de la columna izquierda. A continuación, escriba las mismas expresiones en la barra de búsqueda de Google. Note los resultados. Deberían ser iguales.
JavaScript Google
5 % 3 2 2
26 % 26 0 0
15 % 12 3 3
Intentemos usar un valor negativo como primer operando:
¡Sorpresa!
-5% 3 = 1 (según Google) -5% 3 = -2 (según JavaScript)
Bueno ... esto no debería ser realmente una sorpresa si nos fijamos en la definición de% operator en JavaScript (... o incluso en C # o en muchos otros idiomas). Google calcula el verdadero módulo, mientras que estos lenguajes informáticos calculan un recordatorio firmado.
Sin embargo, no todos los lenguajes de programación / marcos tienen la misma implementación para%. En Python, por ejemplo, el operador% calcula el verdadero módulo de la misma manera que Google.
Esta diferencia en el comportamiento entre idiomas puede introducir errores sutiles en su cálculo, ¡especialmente si está intentando portar un algoritmo de un idioma a otro!
Un problema entendido es un problema medio resuelto.
Supongamos que necesitamos implementar un cálculo (científico) en JavaScript usando aritmética de módulo.
Como ahora entendemos que JavaScript no tiene un verdadero operador de módulo, podemos implementar fácilmente nuestra operación de módulo como una función.
Hay múltiples formas de implementar modulo en JavaScript. Te mostraré 3 formas de hacerlo.
// Implement modulo by replacing the negative operand
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
if ( n < 0 )
n = p - Math.abs(n) % p;
return n % p;
}
// Implement modulo by relying on the fact that the negative remainder
// is always p numbers away from a positive reminder
// Ex: -5 % 3 | -5 = -2 * 3 + 1 and -5 = -1 * 3 + (-2) | -2 + 3 = 1
function mod(n, p)
{
var r = n % p;
return r < 0 ? r + p : r;
}
// Implement modulo by solving n = v * p + r equation
function mod(n, p)
{
return n - p * Math.floor( n / p );
}
Con herramientas más precisas a nuestra disposición, ahora estamos listos para abordar ese cálculo (científico) y esperamos obtener resultados correctos en todo momento.
Nota: Hay muchos cálculos que utilizan la aritmética de módulos ... Si desea ver cómo usar estas nuevas funciones de módulo en la implementación de un código César Cifrado / ROT13, puede consultar este article .
Según la calculadora de Google (-13) % 64
es 51
.
Según Javascript (ver este JSBin ) es -13
.
¿Cómo puedo solucionar esto?
Aunque no se comporta como esperaba, no significa que JavaScript no se esté "comportando". Es una elección de JavaScript hecha para su cálculo de módulo. Porque, por definición, cualquiera de las respuestas tiene sentido.
Vea this de Wikipedia. Puede ver a la derecha cómo diferentes idiomas eligieron el signo del resultado.
De todos modos, aquí hay un tutorial con una función "mod" para obtener un resultado positivo.
var mod = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
mod(5,22) // 5
mod(25,22) // 3
mod(-1,22) // 21
mod(-2,22) // 20
mod(0,22) // 0
mod(-1,22) // 21
mod(-21,22) // 1
Y por supuesto
mod(-13,64) // 51
El operador %
en JavaScript es el operador restante, no el operador de módulo (la principal diferencia es la forma en que se tratan los números negativos):
-1 % 8 // -1, not 7
El uso de Number.prototype
es LENTO, porque cada vez que usa el método prototipo, su número se envuelve en un Object
. En lugar de esto:
Number.prototype.mod = function(n) {
return ((this % n) + n) % n;
}
Utilizar:
function mod(n, m) {
return ((n % m) + m) % m;
}
Consulte: http://jsperf.com/negative-modulo/2
~ 97% más rápido que usar prototipo. Si el desempeño es importante para usted, por supuesto.
Esto no es un error, hay 3 funciones para calcular el módulo, puede usar el que se ajuste a sus necesidades (recomendaría usar la función euclidiana)
Truncando la función de la parte decimal
console.log( 41 % 7 ); // 6
console.log( -41 % 7 ); // -6
console.log( -41 % -7 ); // -6
console.log( 41 % -7 ); // 6
Función de parte entera
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
};
console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // -6
console.log( parseInt( 41).mod(-7) ); // -1
Función euclidiana
Number.prototype.mod = function(n) {
var m = ((this%n)+n)%n;
return m < 0 ? m + Math.abs(n) : m;
};
console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // 1
console.log( parseInt( 41).mod(-7) ); // 6
Hay un paquete NPM que hará el trabajo por usted. Puedes instalarlo con el siguiente comando.
npm install just-modulo --save
Uso copiado desde el README
import modulo from ''just-modulo'';
modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 17
modulo(5.8, 3.4); //2.4
modulo(4, 0); // 4
modulo(-7, 5); // 3
modulo(-2, 15); // 13
modulo(-5.8, 3.4); // 1
modulo(12, -1); // NaN
modulo(-3, -8); // NaN
modulo(12, ''apple''); // NaN
modulo(''bee'', 9); // NaN
modulo(null, undefined); // NaN
El repositorio GitHub se puede encontrar a través del siguiente enlace:
https://github.com/angus-c/just/tree/master/packages/number-modulo
La respuesta aceptada me pone un poco nervioso porque reutiliza el operador%. ¿Qué pasa si Javascript cambia el comportamiento en el futuro?
Aquí hay una solución que no reutiliza%:
function mod(a, n) {
return a - (n * Math.floor(a/n));
}
mod(1,64); // 1
mod(63,64); // 63
mod(64,64); // 0
mod(65,64); // 1
mod(0,64); // 0
mod(-1,64); // 63
mod(-13,64); // 51
mod(-63,64); // 1
mod(-64,64); // 0
mod(-65,64); // 63
Por lo tanto, parece que si estás tratando de hacer modificaciones alrededor de los grados (de modo que si tienes -50 grados - 200 grados), querrás usar algo como:
function modrad(m) {
return ((((180+m) % 360) + 360) % 360)-180;
}
Si x
es un entero y n
es una potencia de 2, puede usar x & (n - 1)
lugar de x % n
.
> -13 & (64 - 1)
51
Trato con negativas y negativas también.
//best perf, hard to read
function modul3(a,n){
r = a/n | 0 ;
if(a < 0){
r += n < 0 ? 1 : -1
}
return a - n * r
}
// shorter code
function modul(a,n){
return a%n + (a < 0 && Math.abs(n));
}
//beetween perf and small code
function modul(a,n){
return a - n * Math[n > 0 ? ''floor'' : ''ceil''](a/n);
}
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
};
Tomado de este artículo: El modulo de JavaScript.