好吧——我几乎不好意思在这里张贴这个(如果有人投票关闭,我会删除),因为这似乎是一个基本的问题。
这是在c++中四舍五入到一个数字的倍数的正确方法吗?
我知道还有其他与此相关的问题,但我特别感兴趣的是,在c++中做这件事的最佳方法是什么:
int roundUp(int numToRound, int multiple)
{
if(multiple == 0)
{
return numToRound;
}
int roundDown = ( (int) (numToRound) / multiple) * multiple;
int roundUp = roundDown + multiple;
int roundCalc = roundUp;
return (roundCalc);
}
更新:
抱歉,我可能没把意思说清楚。下面是一些例子:
roundUp(7, 100)
//return 100
roundUp(117, 100)
//return 200
roundUp(477, 100)
//return 500
roundUp(1077, 100)
//return 1100
roundUp(52, 20)
//return 60
roundUp(74, 30)
//return 90
四舍五入到最接近的倍数,恰好是2的幂
unsigned int round(unsigned int value, unsigned int multiple){
return ((value-1u) & ~(multiple-1u)) + multiple;
}
这在沿中间线分配时很有用,其中您想要的舍入增量是2的幂,但结果值只需是它的倍数。在gcc上,这个函数体生成8条没有除法或分支的汇编指令。
round( 0, 16) -> 0
round( 1, 16) -> 16
round( 16, 16) -> 16
round(257, 128) -> 384 (128 * 3)
round(333, 2) -> 334
这将得到正整数的结果:
#include <iostream>
using namespace std;
int roundUp(int numToRound, int multiple);
int main() {
cout << "answer is: " << roundUp(7, 100) << endl;
cout << "answer is: " << roundUp(117, 100) << endl;
cout << "answer is: " << roundUp(477, 100) << endl;
cout << "answer is: " << roundUp(1077, 100) << endl;
cout << "answer is: " << roundUp(52,20) << endl;
cout << "answer is: " << roundUp(74,30) << endl;
return 0;
}
int roundUp(int numToRound, int multiple) {
if (multiple == 0) {
return 0;
}
int result = (int) (numToRound / multiple) * multiple;
if (numToRound % multiple) {
result += multiple;
}
return result;
}
这里是输出:
answer is: 100
answer is: 200
answer is: 500
answer is: 1100
answer is: 60
answer is: 90
/// Rounding up 'n' to the nearest multiple of number 'b'.
/// - Not tested for negative numbers.
/// \see http://stackoverflow.com/questions/3407012/
#define roundUp(n,b) ( (b)==0 ? (n) : ( ((n)+(b)-1) - (((n)-1)%(b)) ) )
/// \c test->roundUp().
void test_roundUp() {
// yes_roundUp(n,b) ( (b)==0 ? (n) : ( (n)%(b)==0 ? n : (n)+(b)-(n)%(b) ) )
// yes_roundUp(n,b) ( (b)==0 ? (n) : ( ((n + b - 1) / b) * b ) )
// no_roundUp(n,b) ( (n)%(b)==0 ? n : (b)*( (n)/(b) )+(b) )
// no_roundUp(n,b) ( (n)+(b) - (n)%(b) )
if (true) // couldn't make it work without (?:)
{{ // test::roundUp()
unsigned m;
{ m = roundUp(17,8); } ++m;
assertTrue( 24 == roundUp(17,8) );
{ m = roundUp(24,8); }
assertTrue( 24 == roundUp(24,8) );
assertTrue( 24 == roundUp(24,4) );
assertTrue( 24 == roundUp(23,4) );
{ m = roundUp(23,4); }
assertTrue( 24 == roundUp(21,4) );
assertTrue( 20 == roundUp(20,4) );
assertTrue( 20 == roundUp(19,4) );
assertTrue( 20 == roundUp(18,4) );
assertTrue( 20 == roundUp(17,4) );
assertTrue( 17 == roundUp(17,0) );
assertTrue( 20 == roundUp(20,0) );
}}
}