Dividir y Obtener El resto, al mismo tiempo?
Pregunta
Al parecer, x86 (y probablemente muchos otros conjuntos de instrucciones) puso tanto el cociente y el resto de una operación de división en registros separados.
Ahora, podemos probablemente compiladores de confianza para optimizar un código como este para utilizar sólo una llamada a dividir:
( x / 6 )
( x % 6 )
Y probablemente lo hacen. Aún así, hacer cualquier idiomas (o librerías, pero sobre todo buscando idiomas) dando apoyo tanto en la brecha y Modulo resultados al mismo tiempo? Si es así, ¿qué son, y que se ve el sintaxis como?
Solución
C tiene div
y ldiv
. Si éstos generan instrucciones por separado para el cociente y el resto dependerá de su aplicación particular, la biblioteca estándar y los valores de compilación y optimización. A partir de C99, también tiene lldiv
para un número mayor.
Otros consejos
Python hace.
>>> divmod(9, 4)
(2, 1)
¿Qué es impar, becuase Python es un lenguaje de alto nivel tan alto.
Lo mismo sucede con Ruby:
11.divmod(3) #=> [3, 2]
* EDITAR *
Debe tenerse en cuenta que el propósito de estos operadores es, probablemente, no para hacer el trabajo tan eficientemente como sea posible, es más probable que existan las funciones por razones de corrección / portabilidad.
Para los interesados, creo este es el código de la aplicación Python para DIVMOD entero:
static enum divmod_result
i_divmod(register long x, register long y,
long *p_xdivy, long *p_xmody)
{
long xdivy, xmody;
if (y == 0) {
PyErr_SetString(PyExc_ZeroDivisionError,
"integer division or modulo by zero");
return DIVMOD_ERROR;
}
/* (-sys.maxint-1)/-1 is the only overflow case. */
if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x))
return DIVMOD_OVERFLOW;
xdivy = x / y;
/* xdiv*y can overflow on platforms where x/y gives floor(x/y)
* for x and y with differing signs. (This is unusual
* behaviour, and C99 prohibits it, but it's allowed by C89;
* for an example of overflow, take x = LONG_MIN, y = 5 or x =
* LONG_MAX, y = -5.) However, x - xdivy*y is always
* representable as a long, since it lies strictly between
* -abs(y) and abs(y). We add casts to avoid intermediate
* overflow.
*/
xmody = (long)(x - (unsigned long)xdivy * y);
/* If the signs of x and y differ, and the remainder is non-0,
* C89 doesn't define whether xdivy is now the floor or the
* ceiling of the infinitely precise quotient. We want the floor,
* and we have it iff the remainder's sign matches y's.
*/
if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
xmody += y;
--xdivy;
assert(xmody && ((y ^ xmody) >= 0));
}
*p_xdivy = xdivy;
*p_xmody = xmody;
return DIVMOD_OK;
}
En C # / Math.DivRem
NET que tienes:
http://msdn.microsoft.com/en-us/ biblioteca / system.math.divrem.aspx
Sin embargo, según este hilo esto es no tanto una optimización .
Como Stringer Bell mencionó hay DivRem
que no está optimizado hasta .NET 3.5.
En .NET 4.0 utiliza NGen .
Los resultados que obtuve con Math.DivRem
(depuración; liberación = ~ 11000ms)
11863
11820
11881
11859
11854
resultados que obtuve con MyDivRem
(depuración; liberación = ~ 11000ms)
29177
29214
29472
29277
29196
Proyecto dirigido para x86.
ejemplo Math.DivRem
uso
int mod1;
int div1 = Math.DivRem(4, 2, out mod1);
Método firmas
DivRem(Int32, Int32, Int32&) : Int32
DivRem(Int64, Int64, Int64&) : Int64
.NET 4.0 Código
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public static int DivRem(int a, int b, out int result)
{
result = a % b;
return (a / b);
}
.NET 4.0 IL
.custom instance void System.Runtime.TargetedPatchingOptOutAttribute::.ctor(string) = { string('Performance critical to inline across NGen image boundaries') }
.maxstack 8
L_0000: ldarg.2
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: rem
L_0004: stind.i4
L_0005: ldarg.0
L_0006: ldarg.1
L_0007: div
L_0008: ret
El marco .NET tiene Math.DivRem
:
int mod, div = Math.DivRem(11, 3, out mod);
// mod = 2, div = 3
A pesar de que, DivRem
es sólo una envoltura alrededor de algo como esto:
int div = x / y;
int mod = x % y;
(no tengo ni idea de si la lata fluctuación o no / Optimizar hace ese tipo de cosas en una sola instrucción.)
Fwiw, Haskell tiene tanto divMod
y quotRem
que último de los cuales corresponde directamente a la instrucción de máquina (de acuerdo con quot vs. div ), mientras que divMod
no.
int result,rest;
_asm
{
xor edx, edx // pone edx a cero; edx = 0
mov eax, result// eax = 2AF0
mov ecx, radix // ecx = 4
div ecx
mov val, eax
mov rest, edx
}
Esta vuelta el resultado de un resto
int result,rest;
_asm
{
xor edx, edx // pone edx a cero; edx = 0
mov eax, result// eax = 2AF0
mov ecx, radix // ecx = 4
div ecx
mov val, eax
mov rest, edx
}
En Java el BigDecimal
clase tiene la divideAndRemainder
operación de devolución de una matriz de 2 elementos con el resultado y de resto de la división.
BigDecimal bDecimal = ...
BigDecimal[] result = bDecimal.divideAndRemainder(new BigDecimal(60));