【问题标题】:Rounding up to the nearest multiple of a number四舍五入到最接近的数字倍数
【发布时间】:2011-03-25 08:02:49
【问题描述】:

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

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

【问题讨论】:

  • 您的逻辑有误 - 假设我想将 4 舍入到最接近的 2 倍数。roundDown = (4/2) * 2 = 4;向上取整 = 4 + 2;所以 roundCalc = 6。我假设在这种情况下你会想要返回 4。
  • 这不适用于roundUp(30,30)。它给出 60 作为答案,它仍然应该给出 30 作为答案..
  • @bsobaid:在底部查看我的答案。它比这里的其他解决方案稍微简单一些,尽管它们也应该可以工作
  • 您的测试用例明显缺少涉及负数的示例、除法准确的情况、除法几乎准确的情况以及数字非常接近@987654323 范围限制的情况@.
  • Robben_Ford_Fan_boy,应删除带有您所寻求答案的编辑。如果它与给出的答案不同,您可以发布自己的答案。就目前而言,该答案存在应在答案部分解决的问题。

标签: c++ algorithm rounding


【解决方案1】:

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

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;
}

【讨论】:

  • +1 在我看来,这绝对是最好和最易读的解决方案。
  • 在开头添加if(number&lt;0){ multiple = multiple*(-1); } 以正确方向舍入负数
  • @Josh:为什么要使用乘法? if(number&lt;0) multiple = -multiple 更简单。
  • 这不适用于roundUp(30,30)。它给出了 60 作为答案,它仍然应该给出 30 作为答案。
  • @bsobaid 不可能。 if (remainder == 0) 测试应该处理这种情况。它对我有用:ideone.com/Waol7B
【解决方案2】:

无条件:

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

这类似于 rounding away from zero 用于负数

编辑:也适用于负数的版本

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

Tests


如果 multiple 是 2 的幂(快约 3.7 倍 http://quick-bench.com/sgPEZV9AUDqtx2uujRSa3-eTE80

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

Tests

【讨论】:

  • +1 表示 2 版本的幂。非常有用,因为它完全避免了乘法、除法或取模的成本。
  • 你确定这些算法没有前置条件吗?负数呢? The behaviour seems to be undefined in pre-C++11.
  • > 负数呢?如前所述,这适用于负数,例如从零舍入。
  • 我将“四舍五入”理解为向正无穷舍入,而不是从零舍入。
  • 请注意,&amp; ~(x - 1)&amp; -x 的补码算法相同。
【解决方案3】:

当因子始终为正时,此方法有效:

int round_up(int num, int factor)
{
    return num + factor - 1 - (num + factor - 1) % factor;
}

编辑:这将返回round_up(0,100)=100。请参阅下面 Paul 的评论,了解返回 round_up(0,100)=0 的解决方案。

【讨论】:

  • 看起来是处理“已经是多个”案例的最短案例。
  • 就昂贵的操作数量而言的最佳解决方案。它只使用一个除法,没有乘法
  • round_up(0, 100) == 100 而不是接受答案中的 0
  • 不应该是num + factor - 1 - (num + factor - 1) % factor吗?
  • num - 1 - (num - 1) % factor + factor 执行相同的计算,没有整数溢出的风险。
【解决方案4】:

这是对“我如何找出 n 位需要多少字节?(A: (n bits + 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
}

【讨论】:

  • 这不会四舍五入到数字的下一个倍数。
  • 我喜欢这个解决方案,因为如果 roundTo 是 2 的幂,您可以消除 / 和 * 并最终得到便宜的操作 (x = roundTo - 1; return (n+x) &~x;)
  • @Trejkaz 不。应该是 (x = roundTo - 1; return (n+x)&amp;~roundTo;) 在我的回答中
  • @KindDragon 为我产生了错误的结果,但如果我将其更正为 ~x 而不是 ~roundTo,我会得到预期的结果。无论如何,在 Java 8 上。
  • @KindDragon:AND 掩码必须是 0xFFF...000,而不是 0xFFF7FFF 或其他东西,因此您需要 2 的幂或位的 2 的补码否定(-:减号) -翻转一个小于 2 的幂(一个补码逆,~:波浪号不减)。所以(n+x) &amp; ~x(n-roundTo+1) &amp; -roundTo
【解决方案5】:
int roundUp(int numToRound, int multiple)
{
 if(multiple == 0)
 {
  return 0;
 }
 return ((numToRound - 1) / multiple + 1) * multiple;  
}

而且不需要弄乱条件

【讨论】:

    【解决方案6】:

    这是使用模板函数的现代 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 longlong 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 进行舍入。

    创建如下图所示的“向上取整”或更好地称为“圆形天花板”的模板函数:

    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));
    }
    

    【讨论】:

    • 加 1,虽然有些人可能会发现当 mulitple == 0 时返回 0 更合理
    • 当心,因为将 int64_t 转换为 double 可能是有损的,所以它不像看起来那样是泛型的。
    • @AdrianMcCarthy 是的,您必须创建正确的模板特化,如上所示。如您所见,我为long longlong double 实现了两个附加函数。显然,其他两个函数也必须这样做。
    • 我认为这是迄今为止最慢的,但它不一定是。您需要做的就是 std::enable_if_t 并为整数和浮点数做两个分支。您还可以更好地使用 numeric_limits 并查看尾数是否足够大以实际适合该值。这会增加安全性。
    【解决方案7】:

    对于任何寻求简短而甜蜜的答案的人。这是我用的。不考虑负面因素。

    n - (n % r)
    

    这将返回前一个因子。

    (n + r) - (n % r)
    

    将返回下一个。希望这可以帮助某人。 :)

    【讨论】:

    • % 运算符取决于负数的实现——因此在这种情况下可能会得到不同的答案。
    • 我认为重要的是要注意即使数字已经是倍数,这也会返回下一个倍数。为避免这种情况,必须先检查 n % r 是否为零。
    【解决方案8】:
    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;
    }
    

    这适用于任何浮点数或基数(例如,您可以将 -4 舍入到最接近的 6.75)。从本质上讲,它是转换为定点,在那里四舍五入,然后再转换回来。它通过从 0 舍入 AWAY 来处理负数。它还通过本质上将函数转换为 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 的答案,增加了负输入支持。

    【讨论】:

    • 我已经用 double 测试了 float roundUp 代码,它对我有用。真的解决了我的问题。
    • double round(double value, double multiple) { double sign = value; multiple = std::copysign(multiple, 1.0); value = std::copysign(value, 1.0); return std::copysign(multiple * std::ceil(value / multiple), sign); } 怎么样?或者将 ceil 换成 round 以进行舍入。
    【解决方案9】:

    首先,您的错误条件(多个 == 0)应该有一个返回值。什么?我不知道。也许你想抛出一个异常,这取决于你。但是,什么都不返回是危险的。

    其次,您应该检查 numToRound 是否已经是倍数。否则,当您将multiple 添加到roundDown 时,您会得到错误的答案。

    第三,你的演员阵容是错误的。您将numToRound 转换为一个整数,但它已经是一个整数。您需要在除法之前将 to 转换为 double,在乘法之后再转换为 int。

    最后,你想要什么负数?四舍五入“向上”可能意味着四舍五入到零(与正数在相同方向四舍五入)或远离零(“更大”的负数)。或者,也许你不在乎。

    这是一个包含前三个修复的版本,但我不处理负面问题:

    int roundUp(int numToRound, int multiple)
    {
     if(multiple == 0)
     {
      return 0;
     }
     else if(numToRound % multiple == 0)
     {
      return numToRound
     }
    
     int roundDown = (int) (( (double) numToRound / multiple ) * multiple);
     int roundUp = roundDown + multiple; 
     int roundCalc = roundUp;
     return (roundCalc);
    }
    

    【讨论】:

    • @Peter 是吗?我假设int / int 会返回一个int,这不是我们想要的。
    • int / int 确实返回一个 int,但这正是您想要的。例如,numToRound = 7,multiple = 3. 7 / 3 = 2.
    【解决方案10】:

    四舍五入:

    以防万一有人需要将正数四舍五入到最接近的 2 次方倍数的解决方案(因为我就是这样结束的):

    // number: the number to be rounded (ex: 5, 123, 98345, etc.)
    // pow2:   the power to be rounded to (ex: to round to 16, use '4')
    int roundPow2 (int number, int pow2) {
        pow2--;                     // because (2 exp x) == (1 << (x -1))
        pow2 = 0x01 << pow2;
    
        pow2--;                     // because for any
                                    //
                                    // (x = 2 exp x)
                                    //
                                    // subtracting one will
                                    // yield a field of ones
                                    // which we can use in a
                                    // bitwise OR
    
        number--;                   // yield a similar field for
                                    // bitwise OR
        number = number | pow2;
        number++;                   // restore value by adding one back
    
        return number;
    }
    

    如果已经是倍数,输入的数字将保持不变。

    这是 GCC 使用 -O2-Os 提供的 x86_64 输出(9Sep2013 Build - godbolt GCC online):

    roundPow2(int, int):
        lea ecx, [rsi-1]
        mov eax, 1
        sub edi, 1
        sal eax, cl
        sub eax, 1
        or  eax, edi
        add eax, 1
        ret
    

    每行 C 代码都与其在程序集中的行完美对应:http://goo.gl/DZigfX

    这些指令中的每一个都非常快,因此该功能也非常快。由于代码又小又快,在使用的时候inline这个函数可能会有用。


    学分:

    【讨论】:

    • 正是我想要的。谢谢!
    • int roundUpPow2(int num, int pow2) { return num + (pow2 - 1) & ~(pow2 - 1); } 大约快 30%,并且更易于使用(您传递 16 而不是 4 以四舍五入到 16 的下一个倍数。
    【解决方案11】:

    我正在使用:

    template <class _Ty>
    inline _Ty n_Align_Up(_Ty n_x, _Ty n_alignment)
    {
        assert(n_alignment > 0);
        //n_x += (n_x >= 0)? n_alignment - 1 : 1 - n_alignment; // causes to round away from zero (greatest absolute value)
        n_x += (n_x >= 0)? n_alignment - 1 : -1; // causes to round up (towards positive infinity)
        //n_x += (_Ty(-(n_x >= 0)) & n_alignment) - 1; // the same as above, avoids branch and integer multiplication
        //n_x += n_alignment - 1; // only works for positive numbers (fastest)
        return n_x - n_x % n_alignment; // rounds negative towards zero
    }
    

    对于二的幂:

    template <class _Ty>
    bool b_Is_POT(_Ty n_x)
    {
        return !(n_x & (n_x - 1));
    }
    
    template <class _Ty>
    inline _Ty n_Align_Up_POT(_Ty n_x, _Ty n_pot_alignment)
    {
        assert(n_pot_alignment > 0);
        assert(b_Is_POT(n_pot_alignment)); // alignment must be power of two
        -- n_pot_alignment;
        return (n_x + n_pot_alignment) & ~n_pot_alignment; // rounds towards positive infinity (i.e. negative towards zero)
    }
    

    请注意,这两个负值都向零舍入(这意味着所有值都舍入到正无穷大),它们都不依赖于有符号溢出(在 C/C++ 中未定义)。

    这给出了:

    n_Align_Up(10, 100) = 100
    n_Align_Up(110, 100) = 200
    n_Align_Up(0, 100) = 0
    n_Align_Up(-10, 100) = 0
    n_Align_Up(-110, 100) = -100
    n_Align_Up(-210, 100) = -200
    n_Align_Up_POT(10, 128) = 128
    n_Align_Up_POT(130, 128) = 256
    n_Align_Up_POT(0, 128) = 0
    n_Align_Up_POT(-10, 128) = 0
    n_Align_Up_POT(-130, 128) = -128
    n_Align_Up_POT(-260, 128) = -256
    

    【讨论】:

    • 自从我在 Delphi 的 TList 类中看到你的 n_Align_Up_POT 以来,我一直在使用它。它有其限制,例如对齐(多个)是 2 的幂,但这很少成为问题,因为我主要使用它来获取/检查 SMID 的正确对齐。太棒了,好像知道的人不多。
    【解决方案12】:

    转换为浮点数并使用 ceil() 可能更安全 - 除非您知道 int 除法会产生正确的结果。

    【讨论】:

    • 请注意,在基于 x86 的机器上,double 只能保存 54 位有效位。如果你有 64 位整数,它最终会失败。
    • IEEE754 标准双精度不能,但 x64 cpu 具有 80 位内部浮点,因此对单个数字的操作是可靠的
    • 虽然这是真的,但您对 C/C++ 的舍入几乎没有控制权。它取决于控制字设置,它实际上可能舍入到小于 80 位。此外,您还有 SSE 和其他 SIMD 指令集,它们没有这样的扩展中间(矢量化编译器可以轻松使用它们)。
    【解决方案13】:
    int noOfMultiples = int((numToRound / multiple)+0.5);
    return noOfMultiples*multiple
    

    C++ 将每个数字向下舍入,所以如果加上 0.5(如果是 1.5,则为 2),但 1.49 将是 1.99,因此为 1。

    编辑 - 抱歉没有看到你想四舍五入,我建议使用 ceil() 方法而不是 +0.5

    【讨论】:

      【解决方案14】:

      一方面,因为我真的不明白你想做什么,所以线条

      int roundUp = roundDown + multiple;
      int roundCalc = roundUp;
      return (roundCalc); 
      

      绝对可以缩短为

      int roundUp = roundDown + multiple;
      return roundUp;
      

      【讨论】:

        【解决方案15】:

        这可能会有所帮助:

        int RoundUpToNearestMultOfNumber(int val, int num)
        {
          assert(0 != num);
          return (floor((val + num) / num) * num);
        }
        

        【讨论】:

        • 为什么要使用取整除法?没有什么可以铺垫的。如果它是双倍的,你至少可以继承对负值的处理。
        【解决方案16】:

        总是四舍五入

        int alwaysRoundUp(int n, int multiple)
        {
            if (n % multiple != 0) {
                n = ((n + multiple) / multiple) * multiple;
        
                // Another way
                //n = n - n % multiple + multiple;
            }
        
            return n;
        }
        

        alwaysRoundUp(1, 10) -> 10

        alwaysRoundUp(5, 10) -> 10

        alwaysRoundUp(10, 10) -> 10


        总是向下舍入

        int alwaysRoundDown(int n, int multiple)
        {
            n = (n / multiple) * multiple;
        
            return n;
        }
        

        alwaysRoundDown(1, 10) -> 0

        alwaysRoundDown(5, 10) -> 0

        alwaysRoundDown(10, 10) -> 10


        以正常方式舍入

        int normalRound(int n, int multiple)
        {
            n = ((n + multiple/2)/multiple) * multiple;
        
            return n;
        }
        

        normalRound(1, 10) -> 0

        normalRound(5, 10) -> 10

        normalRound(10, 10) -> 10

        【讨论】:

          【解决方案17】:

          四舍五入到恰好是 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
          

          【讨论】:

            【解决方案18】:

            我发现了一种与上面发布的算法有些相似的算法:

            int[(|x|+n-1)/n]*[(nx)/|x|],其中 x 是用户输入的值,n 是使用的倍数。

            它适用于所有值 x,其中 x 是整数(正数或负数,包括零)。我是专门为一个C++程序写的,但是基本上可以用任何语言实现。

            【讨论】:

              【解决方案19】:

              对于负数 numToRound:

              这样做应该很容易,但标准的模 % 运算符不会像人们预期的那样处理负数。例如 -14 % 12 = -2 而不是 10。首先要做的是获得从不返回负数的模运算符。那么roundUp真的很简单。

              public static int mod(int x, int n) 
              {
                  return ((x % n) + n) % n;
              }
              
              public static int roundUp(int numToRound, int multiple) 
              {
                  return numRound + mod(-numToRound, multiple);
              }
              

              【讨论】:

                【解决方案20】:

                这就是我会做的:

                #include <cmath>
                
                int roundUp(int numToRound, int multiple)
                {
                    // if our number is zero, return immediately
                   if (numToRound == 0)
                        return multiple;
                
                    // if multiplier is zero, return immediately
                    if (multiple == 0)
                        return numToRound;
                
                    // how many times are number greater than multiple
                    float rounds = static_cast<float>(numToRound) / static_cast<float>(multiple);
                
                    // determine, whether if number is multiplier of multiple
                    int floorRounds = static_cast<int>(floor(rounds));
                
                    if (rounds - floorRounds > 0)
                        // multiple is not multiplier of number -> advance to the next multiplier
                        return (floorRounds+1) * multiple;
                    else
                        // multiple is multiplier of number -> return actual multiplier
                        return (floorRounds) * multiple;
                }
                

                代码可能不是最优的,但我更喜欢简洁的代码而不是干巴巴的性能。

                【讨论】:

                • int 转换为float 很容易失去精度并导致错误答案。
                【解决方案21】:
                int roundUp (int numToRound, int multiple)
                {
                  return multiple * ((numToRound + multiple - 1) / multiple);
                }
                

                虽然:

                • 不适用于负数
                • 如果 numRound + 多次溢出将不起作用

                建议改用无符号整数,它定义了溢出行为。

                你会得到一个异常是 multiple == 0,但无论如何这不是一个明确定义的问题。

                【讨论】:

                  【解决方案22】:

                  c:

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

                  对于你的 ~/.bashrc:

                  roundup()
                  {
                    echo $(( ${2} ? ((${1}+${2}-1)/${2})*${2} : ${1} ))
                  }
                  

                  【讨论】:

                    【解决方案23】:

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

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

                    我们找到余数的倒数,然后用除数再次取模,如果它是除数本身,则添加x

                    round_up(19, 3) = 21
                    

                    【讨论】:

                      【解决方案24】:

                      这是我根据 OP 的建议以及其他人给出的示例的解决方案。由于大多数人都在寻找它来处理负数,所以这个解决方案就是这样做的,而不使用任何特殊函数,即 abs 等。

                      通过避免取模而使用除法,负数是自然的结果,尽管它是向下舍入的。在计算向下舍入的版本后,它会执行所需的数学运算以向上舍入,无论是在负方向还是正方向。

                      另外请注意,没有使用特殊函数来计算任何东西,所以那里有一个小的速度提升。

                      int RoundUp(int n, int multiple)
                      {
                          // prevent divide by 0 by returning n
                          if (multiple == 0) return n;
                      
                          // calculate the rounded down version
                          int roundedDown = n / multiple * multiple;
                      
                          // if the rounded version and original are the same, then return the original
                          if (roundedDown == n) return n;
                      
                          // handle negative number and round up according to the sign
                          // NOTE: if n is < 0 then subtract the multiple, otherwise add it
                          return (n < 0) ? roundedDown - multiple : roundedDown + multiple;
                      }
                      

                      【讨论】:

                      • 失败,RoundUp(INT_MIN, -1) 因为n / multipleint 溢出。
                      【解决方案25】:

                      我认为这应该对您有所帮助。我用 C 编写了以下程序。

                      # include <stdio.h>
                      int main()
                      {
                        int i, j;
                        printf("\nEnter Two Integers i and j...");
                        scanf("%d %d", &i, &j);
                        int Round_Off=i+j-i%j;
                        printf("The Rounded Off Integer Is...%d\n", Round_Off);
                        return 0;
                      }
                      

                      【讨论】:

                        【解决方案26】:

                        无限可能,仅适用于有符号整数:

                        n + ((r - n) % r)

                        【讨论】:

                          【解决方案27】:
                          /// 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) );
                          }}
                          }
                          

                          【讨论】:

                            【解决方案28】:

                            这是你正在寻找正整数的结果:

                            #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
                            

                            【讨论】:

                              【解决方案29】:

                              我认为这可行:

                              int roundUp(int numToRound, int multiple) {
                                  return multiple? !(numToRound%multiple)? numToRound : ((numToRound/multiple)+1)*multiple: numToRound;
                              }
                              

                              【讨论】:

                                【解决方案30】:

                                这对我有用,但没有尝试处理负面影响

                                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;
                                }
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2012-03-07
                                  • 2011-03-16
                                  • 2021-04-08
                                  • 1970-01-01
                                  • 2016-11-02
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多