簡體   English   中英

將整數舍入到另一個整數的最接近倍數

[英]Rounding integer to nearest multiple of another integer

我需要將整數舍入為另一個整數的最接近的倍數。 在100的倍數的情況下結果的示例:

  • 36-> 0
  • 99-> 100
  • 123-> 100
  • 164-> 200

等等。

我提出了以下代碼,它有效,但感覺“臟”:

int RoundToMultiple(int toRound, int multiple)
{
    return (toRound + (multiple / 2)) / multiple * multiple;
}

這依賴於整數除法的截斷屬性以使其起作用。 我可以指望這個代碼是可移植的嗎? 是否有任何編譯器設置,這將無法給我所需的結果? 如果有,我怎樣才能以便攜方式獲得相同的結果?

如果需要更好的答案,可以假設倍數將是10的冪(包括1的倍數)。 數字也可以假設都是正數。

是的,您可以指望此代碼可移植。 N4296 (這是C ++ 14的最新公開草案)在第5.6節[expr.mul]中說:

對於積分操作數,/運算符產生代數商,丟棄任何小數部分。 [腳注:這通常被稱為截斷為零]

這不是最新C ++的新功能,它也可以在C89中使用。

唯一需要注意的是,如果toRound負數 ,則需要減去偏移量。

另一種方法是:

int RoundToMultiple(int toRound, int multiple)
{
    const auto ratio = static_cast<double>(toRound) / multiple;
    const auto iratio = std::lround(ratio);
    return iratio * multiple;
}

這樣可以避免凌亂的+/-偏移,但性能會更差,如果toRound太大而無法精確地保持雙倍,則會出現問題。 (OTOH,如果這是輸出,那么我懷疑在這種情況下multiple同樣大,所以你會沒事的。)

C ++標准明確地指定了整數除法的行為:

[expr.mul]

對於積分操作數,/運算符產生代數商,丟棄任何小數部分。

Aka截斷為零。 這是便攜式的。

雖然 - 正如其他人所說 - 積分除法的行為與你期望的一樣,但可能是以下解決方案看起來“不那么有線”(仍然基於意見)。

關於將int轉換為double的解決方案:我個人覺得這只是為了四舍五入而昂貴,但也許有人可以說服我,我的感覺是錯的;

無論如何,通過僅使用整數運算符,以下解決方案討論了double的尾數是否總能保持每個int多余:

int RoundToMultiple(int toRound, int multiple) {
    toRound += multiple / 2;
    return toRound - (toRound%multiple);
}

如果您還想包含負值,則可以按如下方式稍微調整代碼(包括測試):

#include <stdio.h>

int RoundToMultiple(int toRound, int multiple) {
    toRound += toRound < 0 ? -multiple / 2 : multiple / 2;
    return toRound - (toRound%multiple);
}

int main(int argc, char const *argv[])
{
    int tests[] = { 36,99,123,164,-36,-99,-123,-164,0 };
    int expectedResults[] = { 0,100,100,200,0,-100,-100,-200,0 };

    int i=0;
    int test=0, result=0, expectedResult=0;
    do {
        test = tests[i];
        result = RoundToMultiple(test, 100);
        expectedResult = expectedResults[i];
        printf("test %d: %d==%d ? %s\n", test, result, expectedResult, (expectedResult==result ? "OK" : "NOK!"));
        i++;
    }
    while(test != 0);
}

暫無
暫無

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

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