test sub mul instruction inc div assembler arithmetic x86 modulo divide

x86 - sub - Divide y consigue el resto al mismo tiempo?



sub instruction assembly (10)

C tiene div y ldiv . Si estos generan instrucciones separadas para el cociente y el resto dependerá de su implementación particular de la biblioteca estándar y la configuración del compilador y la optimización. Comenzando con C99, también tienes lldiv para números más grandes.

Aparentemente, x86 (y probablemente muchos otros conjuntos de instrucciones) ponen tanto el cociente como el resto de una operación dividida en registros separados.

Ahora, probablemente podemos confiar en que los compiladores optimicen un código como este para usar solo una llamada para dividir:

( x / 6 ) ( x % 6 )

Y probablemente lo hagan. Aún así, ¿los idiomas (o bibliotecas, pero principalmente en busca de idiomas) admiten dar los resultados de división y módulo al mismo tiempo? Si es así, ¿qué son y cómo se ve la sintaxis?



Como Stringer Bell mencionó, hay DivRem que no está optimizado hasta .NET 3.5.

En .NET 4.0 usa NGen .

Los resultados que obtuve con Math.DivRem (debug; release = ~ 11000ms)

11863 11820 11881 11859 11854

Resultados que obtuve con MyDivRem (depuración; lanzamiento = ~ 11000 ms)

29177 29214 29472 29277 29196

Proyecto apuntado para x86.

Math.DivRem uso de Math.DivRem

int mod1; int div1 = Math.DivRem(4, 2, out mod1);

Firmas de métodos

DivRem(Int32, Int32, Int32&) : Int32 DivRem(Int64, Int64, Int64&) : Int64

Código .NET 4.0

[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

http://msdn.microsoft.com/en-us/library/system.math.divrem.aspx


El framework .NET tiene http://msdn.microsoft.com/en-us/library/system.math.divrem.aspx :

int mod, div = Math.DivRem(11, 3, out mod); // mod = 2, div = 3

Aunque, DivRem es solo un contenedor de algo como esto:

int div = x / y; int mod = x % y;

(No tengo idea de si el jitter puede / optimiza ese tipo de cosas en una sola instrucción).




Esto devuelve el resultado y el 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 }



Python lo hace.

>>> divmod(9, 4) (2, 1)

Lo cual es extraño, porque Python es un lenguaje de alto nivel.

También lo hace Ruby:

11.divmod(3) #=> [3, 2]

* EDIT *

Cabe señalar que el objetivo de estos operadores es probablemente no hacer el trabajo de la manera más eficiente posible, es más probable que las funciones existan por razones de corrección / portabilidad.

Para los interesados, creo que este es el código de la implementación de 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; }


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 }