Respuestas:
Para un número y
y un divisor, x
calcule el cociente ( quotient
) y el resto ( remainder
) como:
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
y %
juntos no es consistente de esa manera. Use en trunc
lugar de floor
(lo que permite residuos negativos) o use la resta para obtener el resto ( rem = y - div * x
).
rem
de todos modos, se puede obtener el cociente div
más rápido sin Solado: (y - rem) / x
. 2. Por cierto, la operación de módulo según la definición recomendada por Donald Knuth (signo-coincidencias-divisor, no el resto, es decir, el módulo euclidiano, ni el signo-coincidencias-dividendo de JavaScript) es lo que podemos codificar en JavaScript function mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.
No soy un experto en operadores bit a bit, pero aquí hay otra forma de obtener el número entero:
var num = ~~(a / b);
Esto también funcionará correctamente para números negativos, mientras que Math.floor()
se redondeará en la dirección incorrecta.
Esto parece correcto también:
var num = (a / b) >> 0;
a/b | 0
~~int
, int | 0
y int >> 0
no modifica el argumento inicial, pero hace que el intérprete pase la parte integral al operador.
floor
difícilmente se redondea en la dirección incorrecta, dado su nombre, ¡aunque no es la dirección que la gente generalmente quiere!
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
y ~~(a/b)
-> -1231452688
.
~~(5/2) --> 2
como lo hace (5/2)>>0 --> 2
, pero ~~(5/2) + 1 --> 3
, mientras ~~(5/2)>>0 + 1 --> 1
. ~~
Es una buena opción porque la precedencia es más apropiada.
Hice algunas pruebas de velocidad en Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
Lo anterior se basa en 10 millones de ensayos para cada uno.
Conclusión: El uso (a/b>>0)
(o (~~(a/b))
o (a/b|0)
) para lograr el aumento de alrededor del 20% en la eficiencia. También tenga en cuenta que todos son inconsistentes con Math.floor
cuándo a/b<0 && a%b!=0
.
Math.floor
y conocer las otras funciones API de quién sabe cuántos, o aprender sobre el ~
operador (bit a bit) y cómo funcionan las operaciones a nivel de bit en JS y luego comprender el efecto de la doble tilde?
Math.floor
mejor. E incluso si no, este es googleable.
ES6 presenta el nuevo Math.trunc
método. Esto permite corregir la respuesta de @ MarkElliot para que funcione también para números negativos:
var div = Math.trunc(y/x);
var rem = y % x;
Tenga en cuenta que los Math
métodos tienen la ventaja sobre los operadores bit a bit de que trabajan con números superiores a 2 31 .
18014398509481984 == 18014398509481985
.
~~(x/y)
. ¿Necesita admitir números mayores de hasta 54 bits con signo? Úselo Math.trunc
si lo tiene, o de lo Math.floor
contrario (correcto para los números negativos). ¿Necesitas soportar números aún mayores? Use alguna biblioteca de números grandes.
divmod
, puede implementarlo como tal:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:). Lo comprobé con 100,3; -100,3; 100, -3 y -100, -3. Por supuesto, ha pasado mucho tiempo desde su comentario y las cosas cambian.
Normalmente uso:
const quotient = (a - a % b) / b;
const remainder = a % b;
Probablemente no sea el más elegante, pero funciona.
Puede usar la función parseInt
para obtener un resultado truncado.
parseInt(a/b)
Para obtener un resto, use el operador mod:
a%b
parseInt tiene algunas dificultades con las cadenas, para evitar usar el parámetro radix con base 10
parseInt("09", 10)
En algunos casos, la representación de cadena del número puede ser una notación científica, en este caso, parseInt producirá un resultado incorrecto.
parseInt(100000000000000000000000000000000, 10) // 1e+32
Esta llamada producirá 1 como resultado.
parseInt
debe evitarse cuando sea posible. Aquí está la advertencia de Douglas Crockford: "Si el primer carácter de la cadena es 0, entonces la cadena se evalúa en la base 8 en lugar de la base 10. En la base 8, 8 y 9 no son dígitos, entonces parseInt (" 08 ") y parseInt ("09") produce 0 como resultado. Este error causa problemas en los programas que analizan fechas y horas. Afortunadamente, parseInt puede tomar un parámetro de raíz, por lo que parseInt ("08", 10) produce 8. Recomiendo que siempre proporcionar el parámetro radix ". archive.oreilly.com/pub/a/javascript/excerpts/…
parseInt
que se debe evitar; solo que hay algunas trampas a tener en cuenta. Debe ser consciente de estas cosas y estar preparado para hacer frente.
parseInt
con un argumento de número. parseInt
se supone que analiza cadenas parcialmente numéricas, no trunca números.
JavaScript calcula correctamente el piso de números negativos y el resto de números no enteros, siguiendo las definiciones matemáticas para ellos.
FLOOR se define como "el número entero más grande más pequeño que el parámetro", por lo tanto:
RESTANTE se define como el "sobrante" de una división (aritmética euclidiana). Cuando el dividendo no es un número entero, el cociente generalmente tampoco es un número entero, es decir, no hay resto, pero si el cociente se ve obligado a ser un número entero (y eso es lo que sucede cuando alguien intenta obtener el resto o el módulo de un número de punto flotante), obviamente habrá un "entero sobrante" no entero.
JavaScript calcula todo como se esperaba, por lo que el programador debe tener cuidado de hacer las preguntas adecuadas (¡y las personas deben tener cuidado de responder lo que se pregunta!) La primera pregunta de Yarin NO fue "¿cuál es la división entera de X por Y", pero, en su lugar, "TODO el número de veces que un entero dado entra en otro". Para números positivos, la respuesta es la misma para ambos, pero no para números negativos, porque la división entera (dividendo por divisor) será -1 menor que las veces que un número (divisor) "entra" en otro (dividendo). En otras palabras, FLOOR devolverá la respuesta correcta para una división entera de un número negativo, ¡pero Yarin no preguntó eso!
gammax respondió correctamente, ese código funciona según lo solicitado por Yarin. Por otro lado, Samuel está equivocado, no hizo los cálculos, supongo, o habría visto que funciona (también, no dijo cuál era el divisor de su ejemplo, pero espero que fuera 3):
Resto = X% Y = -100% 3 = -1
GoesInto = (X - Remainder) / Y = (-100 - -1) / 3 = -99 / 3 = -33
Por cierto, probé el código en Firefox 27.0.1, funcionó como se esperaba, con números positivos y negativos y también con valores no enteros, tanto para dividendos como para divisores. Ejemplo:
-100.34 / 3.57: Entra = -28, Resto = -0.3800000000000079
Sí, me di cuenta, hay un problema de precisión allí, pero no tuve tiempo de verificarlo (no sé si es un problema con Firefox, Windows 7 o con la FPU de mi CPU). Sin embargo, para la pregunta de Yarin, que solo involucra números enteros, el código del gammax funciona perfectamente.
Math.floor(operation)
devuelve el valor redondeado hacia abajo de la operación.
Ejemplo de 1ª pregunta:
var x = 5;
var y = 10.4;
var z = Math.floor(x + y);
console.log(z);
Consola:
15
Ejemplo de segunda pregunta:
var x = 14;
var y = 5;
var z = Math.floor(x%y);
console.log(x);
Consola:
4 4
Se puede calcular el número de páginas en un solo paso: Math.ceil (x / y)
El comentario de Alex Moore-Niemi como respuesta:
Para Rubyists aquí de Google en busca de divmod
, puede implementarlo como tal:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Resultado:
// [2, 33]
divmod
utiliza la división en pisos ( Math.floor
), que difiere de la división truncada ( Math.trunc
) cuando están involucrados números negativos. Este es el caso del paquete NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
y probablemente también muchas otras implementaciones.
divmod
por lo general, existe porque se realiza dos veces más rápido que calcular las dos operaciones por separado. Proporcionar dicha función sin este beneficio de rendimiento puede ser confuso.
Si solo está dividiendo con potencias de dos, puede usar operadores bit a bit:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(El primero es el cociente, el segundo el resto)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
.
Esto siempre se truncará hacia cero. No estoy seguro si es demasiado tarde, pero aquí va:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Si necesita calcular el resto para enteros muy grandes, que el tiempo de ejecución JS no puede representar como tal (cualquier entero mayor que 2 ^ 32 se representa como flotante y por lo tanto pierde precisión), debe hacer algún truco.
Esto es especialmente importante para verificar muchos casos de dígitos de cheques que están presentes en muchos casos de nuestra vida diaria (números de cuenta bancaria, tarjetas de crédito, ...)
En primer lugar, necesita su número como una cadena (de lo contrario, ya ha perdido precisión y el resto no tiene sentido).
str = '123456789123456789123456789'
Ahora debe dividir su cadena en partes más pequeñas, lo suficientemente pequeñas como para que la concatenación de cualquier resto y un trozo de cuerda pueda caber en 9 dígitos.
digits = 9 - String(divisor).length
Prepare una expresión regular para dividir la cadena.
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
Por ejemplo, si digits
es 7, la expresión regular es
/.{1,7}(?=(.{7})+$)/g
Coincide con una subcadena no vacía de longitud máxima 7, que es seguida ( (?=...)
es una anticipación positiva) por un número de caracteres que es múltiplo de 7. La 'g' es hacer que la expresión se ejecute a través de todas las cadenas, sin detenerse en la primera coincidencia.
Ahora convierta cada parte a entero, y calcule los restos por reduce
(sumando el resto anterior - o 0 - multiplicado por la potencia correcta de 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
Esto funcionará debido al algoritmo de resto de "resta":
n mod d = (n - kd) mod d
que permite reemplazar cualquier 'parte inicial' de la representación decimal de un número con su resto, sin afectar el resto final.
El código final se vería así:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
evalúa a 1.5. Asegúrese de manejar (parseInt, floor, etc.) según sea necesario