Frage C ++ Der beste Weg, um ganzzahlige Division und Rest zu erhalten


Ich frage mich nur, ob ich a by b teilen will und sowohl am Ergebnis c als auch am Rest interessiert bin (zB ob ich eine Anzahl von Sekunden habe und diese in Minuten und Sekunden aufteilen möchte), was ist der beste Weg dazu darüber gehen?

Wäre es

int c = (int)a / b;
int d = a % b;

oder

int c = (int)a / b;
int d = a - b * c;

oder

double tmp = a / b;
int c = (int)tmp;
int d = (int)(0.5+(tmp-c)*b);

oder

vielleicht gibt es eine magische Funktion, die beides auf einmal gibt?


75
2017-08-15 20:21


Ursprung


Antworten:


Auf x86 ist der Rest ein Nebenprodukt der Division selbst, also sollte jeder halbwegs ordentliche Compiler es einfach benutzen können (und nicht a div nochmal). Dies wird wahrscheinlich auch auf anderen Architekturen gemacht.

Anweisung: DIV src

Hinweis: Division ohne Vorzeichen. Dividiert Akkumulator (AX) durch "src". Wenn Teiler   ist ein Byte-Wert, Ergebnis wird auf AL gesetzt und Rest zu AH. Wenn Teiler   ist ein Wortwert, dann wird DX: AX durch "src" geteilt und das Ergebnis gespeichert   in AX und der Rest wird in DX gespeichert.

int c = (int)a / b;
int d = a % b; /* Likely uses the result of the division. */

75
2017-08-15 20:23



std::div gibt eine Struktur mit Ergebnis und Rest zurück.


59
2017-08-15 20:24



Auf mindestens x86 verwendet g ++ 4.6.1 nur IDIVL und ruft beide von dieser einzelnen Anweisung ab.

C ++ - Code:

void foo(int a, int b, int* c, int* d)
{
  *c = a / b;
  *d = a % b;
}

x86-Code:

__Z3fooiiPiS_:
LFB4:
    movq    %rdx, %r8
    movl    %edi, %edx
    movl    %edi, %eax
    sarl    $31, %edx
    idivl   %esi
    movl    %eax, (%r8)
    movl    %edx, (%rcx)
    ret

22
2017-08-15 20:41



Beispielcode testing div () und kombinierte Division & Mod. Ich habe diese mit gcc -O3 kompiliert, ich musste den Aufruf von doNothing hinzufügen, um den Compiler daran zu hindern, alles zu optimieren (Ausgabe wäre 0 für die Division + Mod-Lösung).

Nimm es mit einem Körnchen Salz:

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>

extern doNothing(int,int); // Empty function in another compilation unit

int main() {
    int i;
    struct timeval timeval;
    struct timeval timeval2;
    div_t result;
    gettimeofday(&timeval,NULL);
    for (i = 0; i < 1000; ++i) {
        result = div(i,3);
        doNothing(result.quot,result.rem);
    }
    gettimeofday(&timeval2,NULL);
    printf("%d",timeval2.tv_usec - timeval.tv_usec);
}

Ausgaben: 150

#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>

extern doNothing(int,int); // Empty function in another compilation unit

int main() {
    int i;
    struct timeval timeval;
    struct timeval timeval2;
    int dividend;
    int rem;
    gettimeofday(&timeval,NULL);
    for (i = 0; i < 1000; ++i) {
        dividend = i / 3;
        rem = i % 3;
        doNothing(dividend,rem);
    }
    gettimeofday(&timeval2,NULL);
    printf("%d",timeval2.tv_usec - timeval.tv_usec);
}

Ausgänge: 25


8
2017-08-15 20:57



Zusätzlich zu den oben genannten std :: div Familie von Funktionen gibt es auch die Std :: Remquo Familie von Funktionen, zurück die Rem-ainder und das bekommen Quo-tient über einen übergebenen Zeiger.

[Bearbeiten:] Es sieht aus wie std :: remquo gibt den Quotienten nicht wirklich zurück Letztendlich.


5
2017-09-19 18:56



Wenn alles andere gleich ist, ist die beste Lösung diejenige, die Ihre Absicht deutlich zum Ausdruck bringt. Damit:

int totalSeconds = 453;
int minutes = totalSeconds / 60;
int remainingSeconds = totalSeconds % 60;

ist wahrscheinlich die beste der drei Optionen, die Sie vorgestellt haben. Wie in anderen Antworten erwähnt, ist die div Methode berechnet beide Werte für Sie auf einmal.


3
2017-08-15 20:27



Sie können g ++ 4.6.3 hier nicht mit 64-Bit-Ganzzahlen auf einer 32-Bit-Intel-Plattform vertrauen. a / b wird durch einen Aufruf von divdi3 berechnet, und ein% b wird durch einen Aufruf von moddi3 berechnet. Ich kann sogar ein Beispiel finden, das a / b und a-b * (a / b) mit diesen Aufrufen berechnet. Also benutze ich c = a / b und a-b * c.

Die Div-Methode gibt einen Aufruf an eine Funktion, die die Div-Struktur berechnet, aber ein Funktionsaufruf scheint auf Plattformen, die Hardwareunterstützung für den Integraltyp haben (d. H. 64-Bit-Ganzzahlen auf 64-Bit-Intel / AMD-Plattformen), ineffizient zu sein.


3
2018-05-04 01:38



Sie können einen Modulus verwenden, um den Rest zu erhalten. Obwohl @ cnicutars Antwort sauberer / direkter erscheint.


-4
2017-08-15 20:26