139 votes

C ++ Meilleur moyen d'obtenir la division entière et le reste

Je me demande simplement, si je veux diviser a par b, et que je suis intéressé à la fois par le résultat c et par le reste (par exemple, disons que j’ai le nombre de secondes et que je souhaite le scinder en minutes et en secondes), quel est le meilleur moyen de aller à ce sujet?

Serait-ce

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

ou

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

ou

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

ou

peut-être il y a une fonction magique qui donne un à la fois?

134voto

cnicutar Points 98451

Sur x86, le reste est un sous-produit de la division elle-même de sorte que toute demi-décent compilateur doit être en mesure d'utiliser (et de ne pas effectuer une div ). C'est probablement le cas sur d'autres architectures.

Instruction: DIV src

Remarque: Unsigned division. Divise accumulateur (AX) par "src". Si le diviseur est un octet de valeur, le résultat est mis à AL et reste à l'AH. Si le diviseur est un mot valeur, alors DX:AX est divisé par "src" et le résultat est stocké dans AX et le reste est stocké dans DX.

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

126voto

pezcode Points 2596

std::div renvoie une structure contenant à la fois le résultat et le reste.

37voto

Peter Alexander Points 31990

Sur au moins x86, g ++ 4.6.1 utilise simplement IDIVL et obtient les deux à partir de cette instruction unique.

Code C ++:

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

code x86:

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

13voto

Greg Howell Points 685

Exemple de code test div () et division & mod. Je les ai compilés avec gcc -O3, il a fallu ajouter l’appel à doNothing pour empêcher le compilateur d’optimiser tout le fonctionnement (la sortie serait 0 pour la solution division + mod).

Prenez-le avec un grain de sel:

 #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);
}
 

Sorties: 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);
}
 

Sorties: 25

7voto

Jamin Grey Points 2323

En plus de la famille de fonctions std :: div susmentionnée, il existe également la famille de fonctions std :: remquo , renvoie le rem -ainder et obtient le statu quo via un pointeur passé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X