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

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

当前回答

没有条件:

int roundUp(int numToRound, int multiple) 
{
    assert(multiple);
    return ((numToRound + multiple - 1) / multiple) * multiple;
}

这就像对负数进行舍入一样


同样适用于负数的版本:

int roundUp(int numToRound, int multiple) 
{
    assert(multiple);
    int isPositive = (int)(numToRound >= 0);
    return ((numToRound + isPositive * (multiple - 1)) / multiple) * multiple;
}

测试


如果倍数是2的幂(快3.7倍)

int roundUp(int numToRound, int multiple) 
{
    assert(multiple && ((multiple & (multiple - 1)) == 0));
    return (numToRound + multiple - 1) & -multiple;
}

测试

其他回答

这是对“如何求出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
}

这是使用模板函数的现代c++方法,该模板函数适用于float, double, long, int和short(但不适用于long long和long double,因为使用了double值)。

#include <cmath>
#include <iostream>

template<typename T>
T roundMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::round(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

int main()
{
    std::cout << roundMultiple(39298.0, 100.0) << std::endl;
    std::cout << roundMultiple(20930.0f, 1000.0f) << std::endl;
    std::cout << roundMultiple(287399, 10) << std::endl;
}

但是你可以很容易地通过模板专门化添加long long和long double的支持,如下所示:

template<>
long double roundMultiple<long double>( long double value, long double multiple)
{
    if (multiple == 0.0l) return value;
    return std::round(value/multiple)*multiple;
}

template<>
long long roundMultiple<long long>( long long value, long long multiple)
{
    if (multiple == 0.0l) return value;
    return static_cast<long long>(std::round(static_cast<long double>(value)/static_cast<long double>(multiple))*static_cast<long double>(multiple));
}

要创建向上舍入的函数,请使用std::ceil,而总是向下舍入的函数请使用std::floor。上面的例子是使用std::round进行舍入。

创建“round up”或更广为人知的“round ceiling”模板函数,如下所示:

template<typename T>
T roundCeilMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::ceil(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

创建“round down”或更广为人知的“round floor”模板函数,如下所示:

template<typename T>
T roundFloorMultiple( T value, T multiple )
{
    if (multiple == 0) return value;
    return static_cast<T>(std::floor(static_cast<double>(value)/static_cast<double>(multiple))*static_cast<double>(multiple));
}

这适用于正数,不适用于负数。它只使用整数数学。

int roundUp(int numToRound, int multiple)
{
    if (multiple == 0)
        return numToRound;

    int remainder = numToRound % multiple;
    if (remainder == 0)
        return numToRound;

    return numToRound + multiple - remainder;
}

编辑:这里有一个适用于负数的版本,如果你所说的“上”是指一个总是>=输入的结果。

int roundUp(int numToRound, int multiple)
{
    if (multiple == 0)
        return numToRound;

    int remainder = abs(numToRound) % multiple;
    if (remainder == 0)
        return numToRound;

    if (numToRound < 0)
        return -(abs(numToRound) - remainder);
    else
        return numToRound + multiple - remainder;
}

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

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,所以输入值不变。

这对我来说很管用,但我并没有试图处理消极的东西

public static int roundUp(int numToRound, int multiple) {
    if (multiple == 0) {
        return 0;
    } else if (numToRound % multiple == 0) {
    return numToRound;
    }

    int mod = numToRound % multiple;
    int diff = multiple - mod;
    return numToRound + diff;
}