好吧——我几乎不好意思在这里张贴这个(如果有人投票关闭,我会删除),因为这似乎是一个基本的问题。

这是在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

当前回答

float roundUp(float number, float fixedBase) {
    if (fixedBase != 0 && number != 0) {
        float sign = number > 0 ? 1 : -1;
        number *= sign;
        number /= fixedBase;
        int fixedPoint = (int) ceil(number);
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

这适用于任何浮点数或基数(例如,你可以四舍五入到最接近的6.75)。本质上,它是转换到定点,四舍五入,然后转换回来。它通过舍入0来处理负号。它还通过将函数转换为roundDown来处理值的负舍入。

int特定的版本如下所示:

int roundUp(int number, int fixedBase) {
    if (fixedBase != 0 && number != 0) {
        int sign = number > 0 ? 1 : -1;
        int baseSign = fixedBase > 0 ? 1 : 0;
        number *= sign;
        int fixedPoint = (number + baseSign * (fixedBase - 1)) / fixedBase;
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

这或多或少是plinth的答案,加上负输入支持。

其他回答

四舍五入到最接近的倍数,恰好是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

公认的答案并不是很好,我想我应该在这个问题上尝试一下,这应该是你抛出的所有整数:

int round_up(int input, unsigned int multiple) {
    if (input < 0) { return input - input % multiple; }
    return input + multiple - (((input - 1) % multiple) + 1);
}

如果这个数是负的,这很简单,取余数并把它加到输入上,这就可以了。

如果这个数不是负的,你必须从倍数中减去余数,然后加上它来四舍五入。问题是,如果输入正好在一个倍数上,它仍然会四舍五入到下一个倍数,因为倍数- 0 =倍数。

为了解决这个问题,我们做了一个很酷的小技巧:在计算余数之前从输入中减去1,然后把它加回到结果的余数上。这不会影响任何东西,除非输入是倍数。在这种情况下,减去1将计算出前一个倍数的余数。再加1,就正好是这个倍数。很明显,从自身减去这个等于0,所以输入值不变。

float roundUp(float number, float fixedBase) {
    if (fixedBase != 0 && number != 0) {
        float sign = number > 0 ? 1 : -1;
        number *= sign;
        number /= fixedBase;
        int fixedPoint = (int) ceil(number);
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

这适用于任何浮点数或基数(例如,你可以四舍五入到最接近的6.75)。本质上,它是转换到定点,四舍五入,然后转换回来。它通过舍入0来处理负号。它还通过将函数转换为roundDown来处理值的负舍入。

int特定的版本如下所示:

int roundUp(int number, int fixedBase) {
    if (fixedBase != 0 && number != 0) {
        int sign = number > 0 ? 1 : -1;
        int baseSign = fixedBase > 0 ? 1 : 0;
        number *= sign;
        int fixedPoint = (number + baseSign * (fixedBase - 1)) / fixedBase;
        number = fixedPoint * fixedBase;
        number *= sign;
    }
    return number;
}

这或多或少是plinth的答案,加上负输入支持。

这是对“如何求出n位需要多少字节?”(A:(n位+ 7)/ 8)。

int RoundUp(int n, int roundTo)
{
    // fails on negative?  What does that mean?
    if (roundTo == 0) return 0;
    return ((n + roundTo - 1) / roundTo) * roundTo; // edit - fixed error
}

如果x已经是一个倍数,我使用模的组合来取消余数的加法:

int round_up(int x, int div)
{
    return x + (div - x % div) % div;
}

我们求余数的倒数然后再用除数求模如果它是除数本身,再加上x。

round_up(19, 3) = 21