C++ лучший способ получить целочисленное деление и остаток


мне просто интересно, если я хочу разделить a на b, и меня интересует как результат c, так и остаток (например, скажем, у меня есть количество секунд и я хочу разделить это на минуты и секунды), каков наилучший способ сделать это?

будет

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

или

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

или

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

или

может быть, есть магическая функция, которая дает одно и то же сразу?

8 78

8 ответов:

на x86 остаток является побочным продуктом самого разделения, поэтому любой наполовину приличный компилятор должен иметь возможность просто использовать его (а не выполнять div снова). Вероятно, это делается и на других архитектурах.

инструкция: DIV src

Примечание: беззнаковое деление. Делит аккумулятор (AX) на "src". Если делитель это байтовое значение, результат ставится в AL а остальное к ах. Если делитель является значением слова, то DX: AX делится на " src" и результат сохраняется в топор а остаток хранится в DX.

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

std::div возвращает структуру с результатом и остатком.

на x86 по крайней мере, g++ 4.6.1 просто использует IDIVL и получает оба из этой единственной инструкции.

C++ код:

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

x86 код:

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

пример кода тестирования div () и комбинированное разделение & mod. Я скомпилировал их с помощью gcc-O3, мне пришлось добавить вызов doNothing, чтобы остановить компилятор от оптимизации всего (выход будет равен 0 для решения division + mod).

возьмите его с солью:

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

выходы: 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);
}

выходы: 25

В дополнение к вышеупомянутым std:: div семейство функций, есть также std:: remquo семейство функций, возвратить rem-ainder и получение quo-tient через переданный указатель.

[Edit:] похоже на std:: remquo на самом деле не возвращает фактор В конце концов.

при прочих равных условиях, лучшим решением является тот, который четко выражает ваши намерения. Итак:

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

вероятно, это лучший из трех вариантов, которые вы представили. Как отмечалось в других ответах, однако,div метод вычислит оба значения для вас сразу.

вы не можете доверять g++ 4.6.3 здесь с 64-битными целыми числами на 32-битной платформе intel. a / b вычисляется вызовом divdi3, А%b вычисляется вызовом moddi3. Я даже могу придумать пример, который вычисляет a/b и a-b*(a / b) с этими вызовами. Поэтому я использую c=A / b и a-b*c.

метод div дает вызов функции, которая вычисляет структуру div, но вызов функции кажется неэффективным на платформах, которые имеют аппаратную поддержку для интегрального типа (т. е. 64-битные целые числа на 64-битные платформы intel / amd).

вы можете использовать модуль, чтобы получить остаток. Хотя ответ @cnicutar кажется более чистым / более прямым.