2017-05-22 131 views
6

我需要將整數舍入爲另一個整數的最接近倍數。將整數舍入到另一個整數的最接近倍數

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

等:在100的倍數的情況下的結果的例子上。

我想出了下面的代碼,這樣的作品,但感覺「髒」:

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

此計算整數除法的截斷特性,使其工作。 我可以指望這個代碼是可移植的嗎?是否有任何編譯器設置,這將無法給我想要的結果?如果有,我怎樣才能以便攜的方式獲得相同的結果?

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

+0

這可能不適用於負數。 – Gerriet

+0

@Gerriet好點,雖然在我的情況下,數字也可以假設爲正數。我將它添加到問題 –

+0

您想要RoundToMultiple(150,100)表現如何?它應該返回100還是200?換句話說,整理,整理或使用銀行家的舍入規則? –

回答

4

是的,你可以指望這個代碼是可移植的。 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在這種情況下會類似的大,所以你會沒事的。)

+0

['int'數不能超過'double'使精度(https://stackoverflow.com/questions/3793838/which- is-the-first-integer-that-an-ieee-754-float-is-incapable-of-represent-e),所以你可能不需要關於'toRound'的警告變得太大。 – Xirema

+0

@Xirema不好意思,但是在你發佈的那個鏈接裏,它說int精度不能超過雙精度? –

+0

@KlitosKyriacou [該訊息的第一應答(https://stackoverflow.com/a/3793950/5241642)。 「double」給出的數字大於「int」的最大範圍。 – Xirema

2

C++標準明確指定整數除法正是如此的行爲:

[expr.mul]

對於整型操作數的/操作者產生的代數 商數與丟棄任何小數部分。

A.k.a.截至零。這是隨機獲得的。

0

雖然 - 正如別人提到的那樣 - 積分的行爲就像你期望的那樣,可能是以下解決方案看起來「不那麼有線」(仍然基於觀點)。

關於一種轉換INT爲雙重的解決方案:我個人覺得這是昂貴的只是四捨五入的原因,但也許有人能說服我,我的感覺是錯誤的;

不管怎樣,僅僅通過使用積分算,以下解決方案使上是否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); 
} 
相關問題