Teilen Sie und den Rest zur gleichen Zeit erhalten?
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?
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
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: