Frage

Offenbar x86 (und wahrscheinlich auch eine Menge anderer Befehlssätze) stellen sowohl den Quotienten und den Rest einer Teilungsoperation in getrennten Registern.

Jetzt können wir wahrscheinlich Vertrauen Compiler einen Code zu optimieren, wie dies nur ein Aufruf zu teilen verwenden:

( x / 6 )
( x % 6 )

Und das tun sie wahrscheinlich. Dennoch tun alle Sprachen (oder Bibliotheken, sondern vor allem für Sprachen suchen) Unterstützung sowohl die Kluft zu geben und Modulo Ergebnisse zur gleichen Zeit? Wenn ja, was sind sie, und was bedeutet die Syntax aus?

War es hilfreich?

Lösung

C hat div und ldiv . Ob diese erzeugen separate Anleitung für den Quotienten und den Rest auf Ihrer bestimmten Standard-Bibliothek Implementierung und Compiler und Optimierungseinstellungen abhängen. Beginnend mit C99, haben Sie auch lldiv für größere Zahlen.

Andere Tipps

Python hat.

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

Welche ungerade ist, becuase Python ist eine solche Hochsprache.

Das Gleiche gilt für Rubin:

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

* EDIT *

Es ist zu beachten, dass der Zweck dieser Operatoren ist wahrscheinlich nicht die Arbeit so effizient wie möglich zu tun, es ist wahrscheinlich die Funktionen existieren für Richtigkeit / Portabilität Gründe.

Für Interessenten, glaube ich, dies der Code ist die Python-Implementierung für integer divmod:

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;
}
.

In C # / NET Sie haben Math.DivRem: http://msdn.microsoft.com/en-us/ Bibliothek / system.math.divrem.aspx

Aber nach dieses Thema dies ist nicht so sehr eine Optimierung .

Wie Stringer Bell-erwähnt gibt DivRem ist die nicht optimiert bis zu .NET 3.5.

Auf .NET 4.0 es verwendet NGen .

Die Ergebnisse, die ich mit Math.DivRem bekam (debug; Release = ~ 11000ms)

11863
11820
11881
11859
11854

Ergebnisse Ich habe mit MyDivRem (debug; Release = ~ 11000ms)

29177
29214
29472
29277
29196

Projekt für x86 abgezielt.


Math.DivRem Anwendungsbeispiel

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

Methode Signaturen

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

Die .NET-Framework hat Math.DivRem :

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

Obwohl DivRem ist nur ein Wrapper um so etwas wie folgt aus:

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

(Ich habe keine Ahnung, ob der Jitter / tut optimize dieser Art der Sache in einen einzigen Befehl.)

FWIW, hat Haskell beide divMod und quotRem dass welche letztere entspricht direkt den Maschinenbefehl (entsprechend Integral Operatoren quot vs. div ), während divMod auch nicht.

    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
    }

Diese Rückkehr ist das Ergebnis eines de Rest

        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
    }

In Java der Klasse BigDecimal hat den Betrieb divideAndRemainder eine Anordnung von zwei Elementen mit dem Ergebnis und de Rest der Division zurück.

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

Javadoc:

scroll top