Question

Apparemment, x86 (et probablement beaucoup d'autres jeux d'instructions) mis à la fois le quotient et le reste d'une opération de division dans des registres séparés.

Maintenant, nous pouvons probablement compilateurs de confiance pour optimiser un code tel que celui d'utiliser un seul appel à diviser:

( x / 6 )
( x % 6 )

Et ils le font sans doute. Pourtant, faire des langues (ou les bibliothèques, mais principalement à la recherche pour les langues) le soutien donnant à la fois la fracture et modulo résultats en même temps? Si oui, quels sont-ils, et Qu'est-ce que l'apparence de la syntaxe comme?

Était-ce utile?

La solution

C a div et ldiv . Que ceux-ci générer des instructions séparées pour le quotient et le reste dépendra de votre mise en œuvre bibliothèque standard particulier et les paramètres du compilateur et d'optimisation. A partir de C99, vous avez également lldiv pour un plus grand nombre.

Autres conseils

Python fait.

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

Ce qui est étrange, Python est becuase un langage de haut niveau.

fait Ruby:

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

* EDIT *

Il convient de noter que le but de ces opérateurs est probablement de ne pas faire le travail le plus efficacement possible, il est plus probable que les fonctions existent pour des raisons exactitude / portabilité.

Pour les intéressés, je crois que c'est le code de la mise en œuvre python pour divmod entier:

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 # / NET que vous avez Math.DivRem: http://msdn.microsoft.com/en-us/ bibliothèque / system.math.divrem.aspx

Mais selon ce fil ce n'est pas tant que ça une optimisation .

Stringer Bell a mentionné il y a DivRem qui est pas optimisé jusqu'à .NET 3.5.

Le .NET 4.0 utilise NGen.

Les résultats que j'ai obtenu avec Math.DivRem (debug, release = ~ 11000ms)

11863
11820
11881
11859
11854

Résultats je suis arrivé avec MyDivRem (debug, release = ~ 11000ms)

29177
29214
29472
29277
29196

Projet ciblé pour x86.


Math.DivRem Exemple d'utilisation

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

Méthode de

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

.NET 4.0 code

[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 Reference

Le framework .NET a Math.DivRem :

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

Bien que, DivRem est juste une enveloppe autour de quelque chose comme ceci:

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

(Je ne sais pas si oui ou non la boîte de gigue / ne optimise ce genre de choses en une seule instruction.)

FWIW, Haskell a à la fois divMod et quotRem celui-ci qui correspond directement à l'instruction de machine (selon opérateurs intégraux quot vs div ) tandis que divMod ne peut pas.

    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
    }

Ce retour le résultat d'un reste de

        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 le BigDecimal de classe a l'opération divideAndRemainder retourne un tableau de 2 éléments du résultat et de reste de la division.

BigDecimal bDecimal = ...
BigDecimal[] result = bDecimal.divideAndRemainder(new BigDecimal(60));

Javadoc:

scroll top