簡體   English   中英

C++ 獲得 integer 除法和余數的最佳方法

[英]C++ Best way to get integer division and remainder

我只是想知道,如果我想將 a 除以 b,並且對結果 c 和其余部分感興趣(例如,我有秒數並想將其分成分鍾和秒),那么最好的方法是什么go 關於它?

可不可能是

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

或者

也許有一個神奇的 function 可以同時給一個?

在 x86 上,余數是除法本身的副產品,因此任何半體面的編譯器都應該能夠只使用它(並且不再執行div )。 這也可能在其他架構上完成。

指令: DIV src

注:無符號除法。 將累加器 (AX) 除以“src”。 如果除數是字節值,則將結果放入 AL並將余數放入 AH 如果除數是字值,則 DX:AX 除以“src”,結果存儲在 AX 中,余數存儲在 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    $31, %edx
    idivl   %esi
    movl    %eax, (%r8)
    movl    %edx, (%rcx)
    ret

示例代碼測試 div() 和組合除法 & mod。 我用 gcc -O3 編譯了這些,我必須添加對 doNothing 的調用以阻止編譯器優化所有內容(除法 + mod 解決方案的輸出將為 0)。

帶上一粒鹽:

#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。

[編輯:]看起來 std::remquo 畢竟並沒有真正返回商

在其他條件相同的情況下,最好的解決方案是明確表達您的意圖。 所以:

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

可能是您提出的三個選項中最好的一個。 但是,正如其他答案中所述, div方法將同時為您計算這兩個值。

您不能相信 g++ 4.6.3 在 32 位英特爾平台上使用 64 位整數。 a/b 是通過調用 divdi3 來計算的,a%b 是通過調用 moddi3 來計算的。 我什至可以想出一個用這些調用計算 a/b 和 ab*(a/b) 的例子。 所以我使用 c=a/b 和 ab*c。

div 方法調用了計算 div 結構的 function,但 function 調用在硬件支持整數類型的平台上似乎效率低下(即 64 位 intel/amd 平台上的 64 位整數)。

許多答案建議使用以下代碼:

int div = a / b;
int mod = a % b;

但是,值得記住的是,除法與乘法不同,加法的執行時間要長得多(據我所知,時鍾周期是一個時鍾周期的幾十倍)。 並且,如果需要反復計算mod和div,那么值得用一除一乘一加代替二除,如下:

int div = a / b;
int mod = a - div * b;

您可以使用模數來獲得余數。 盡管@cnicutar 的回答似乎更干凈/更直接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM