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 ответов:
на 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).