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?

¿Fue útil?

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 

MSDN referencia

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));

Javadoc: https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divideAndRemainder (java.math.BigDecimal)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top