Diviser et obtenir en même Remainder temps?
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?
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 .
Common Lisp fait: http://www.lispworks.com/documentation/ hyperspec / corps / f_floorc.htm
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
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: