安全地舍入到下一个较小的倍数

时间:2015-11-27 11:23:56

标签: c++

考虑:

int a, b;
int c = b * (a / b)

我认为它应该非常清楚对正数的作用:c​​被设置为b的倍数,相对于a来说,它是下一个小的。

示例:设b = 2,然后:

a = 0 => c = 0
a = 1 => c = 0
a = 2 => c = 2
a = 3 => c = 2

然而,对于负数,它的工作方式相反:它需要b的下一个更大(更少负)的倍数。 选择b的下一个较小(更负)的倍数的最佳方法是什么?

3 个答案:

答案 0 :(得分:4)

怎么样:

#include <cstdlib>
#include <iostream>

int round_down(int val, int unit) {
  std::div_t div_result = std::div(val, unit);
  int candidate = div_result.quot * unit;
  return candidate <= val ? candidate : 
         unit >= 0 ? candidate - unit :
         candidate + unit;
}

int main() {
  std::cout << round_down(9, 7) << std::endl;
  std::cout << round_down(13, 2) << std::endl;
  std::cout << round_down(15, 3) << std::endl;

  std::cout << round_down(-9, 7) << std::endl;
  std::cout << round_down(-13, 2) << std::endl;
  std::cout << round_down(-15, 3) << std::endl;

  std::cout << round_down(9, -7) << std::endl;
  std::cout << round_down(13, -2) << std::endl;
  std::cout << round_down(15, -3) << std::endl;

  std::cout << round_down(-9, -7) << std::endl;
  std::cout << round_down(-13, -2) << std::endl;
  std::cout << round_down(-15, -3) << std::endl;
}

请注意,在C ++ 11之前,内置除法运算符/的舍入方向是实现定义的。所以,我正在使用std::div()。引自cppreference(强调我的):

  

二元运算符/将第一个操作数除以第二个(后   通常的算术转换)   对于积分操作数,它产生了   代数商   商在实现定义的方向上舍入。 (直到C ++ 11)
  商是   截断为零(丢弃小数部分)。 (自C ++ 11起)
  ...
  注意:在C ++ 11之前,如果二元运算符的一个或两个操作数%   是否定的,余数的符号是​​实现定义的,   因为它取决于整数除法的舍入方向。的的   函数std :: div在这种情况下提供了明确定义的行为。

答案 1 :(得分:1)

您需要在b+1 a之前从a<0中删除#include <iostream> using namespace std; int main() { cout << "---------------------------------" << endl; for (int bi = 1; bi < 10; bi++) { for (int ai = -10; ai < 10; ai++) { int a = ai; int b = bi; if (a < 0) a -= b + 1; int c = b * (std::div(a / b)); cout << "a = " << a << ",b = " << b << " => c = " << c << endl; } cout << "---------------------------------" << endl; } } ,然后才能将其传递给您的函数:

---------------------------------
a = -12,b = 1 => c = -12
a = -11,b = 1 => c = -11
a = -10,b = 1 => c = -10
a = -9,b = 1 => c = -9
a = -8,b = 1 => c = -8
a = -7,b = 1 => c = -7
a = -6,b = 1 => c = -6
a = -5,b = 1 => c = -5
a = -4,b = 1 => c = -4
a = -3,b = 1 => c = -3
a = 0,b = 1 => c = 0
a = 1,b = 1 => c = 1
a = 2,b = 1 => c = 2
a = 3,b = 1 => c = 3
a = 4,b = 1 => c = 4
a = 5,b = 1 => c = 5
a = 6,b = 1 => c = 6
a = 7,b = 1 => c = 7
a = 8,b = 1 => c = 8
a = 9,b = 1 => c = 9
---------------------------------
a = -13,b = 2 => c = -12
a = -12,b = 2 => c = -12
a = -11,b = 2 => c = -10
a = -10,b = 2 => c = -10
a = -9,b = 2 => c = -8
a = -8,b = 2 => c = -8
a = -7,b = 2 => c = -6
a = -6,b = 2 => c = -6
a = -5,b = 2 => c = -4
a = -4,b = 2 => c = -4
a = 0,b = 2 => c = 0
a = 1,b = 2 => c = 0
a = 2,b = 2 => c = 2
a = 3,b = 2 => c = 2
a = 4,b = 2 => c = 4
a = 5,b = 2 => c = 4
a = 6,b = 2 => c = 6
a = 7,b = 2 => c = 6
a = 8,b = 2 => c = 8
a = 9,b = 2 => c = 8
---------------------------------
a = -14,b = 3 => c = -12
a = -13,b = 3 => c = -12
a = -12,b = 3 => c = -12
a = -11,b = 3 => c = -9
a = -10,b = 3 => c = -9
a = -9,b = 3 => c = -9
a = -8,b = 3 => c = -6
a = -7,b = 3 => c = -6
a = -6,b = 3 => c = -6
a = -5,b = 3 => c = -3
a = 0,b = 3 => c = 0
a = 1,b = 3 => c = 0
a = 2,b = 3 => c = 0
a = 3,b = 3 => c = 3
a = 4,b = 3 => c = 3
a = 5,b = 3 => c = 3
a = 6,b = 3 => c = 6
a = 7,b = 3 => c = 6
a = 8,b = 3 => c = 6
a = 9,b = 3 => c = 9
---------------------------------
a = -15,b = 4 => c = -12
a = -14,b = 4 => c = -12
a = -13,b = 4 => c = -12
a = -12,b = 4 => c = -12
a = -11,b = 4 => c = -8
a = -10,b = 4 => c = -8
a = -9,b = 4 => c = -8
a = -8,b = 4 => c = -8
a = -7,b = 4 => c = -4
a = -6,b = 4 => c = -4
a = 0,b = 4 => c = 0
a = 1,b = 4 => c = 0
a = 2,b = 4 => c = 0
a = 3,b = 4 => c = 0
a = 4,b = 4 => c = 4
a = 5,b = 4 => c = 4
a = 6,b = 4 => c = 4
a = 7,b = 4 => c = 4
a = 8,b = 4 => c = 8
a = 9,b = 4 => c = 8
---------------------------------
a = -16,b = 5 => c = -15
a = -15,b = 5 => c = -15
a = -14,b = 5 => c = -10
a = -13,b = 5 => c = -10
a = -12,b = 5 => c = -10
a = -11,b = 5 => c = -10
a = -10,b = 5 => c = -10
a = -9,b = 5 => c = -5
a = -8,b = 5 => c = -5
a = -7,b = 5 => c = -5
a = 0,b = 5 => c = 0
a = 1,b = 5 => c = 0
a = 2,b = 5 => c = 0
a = 3,b = 5 => c = 0
a = 4,b = 5 => c = 0
a = 5,b = 5 => c = 5
a = 6,b = 5 => c = 5
a = 7,b = 5 => c = 5
a = 8,b = 5 => c = 5
a = 9,b = 5 => c = 5
---------------------------------
a = -17,b = 6 => c = -12
a = -16,b = 6 => c = -12
a = -15,b = 6 => c = -12
a = -14,b = 6 => c = -12
a = -13,b = 6 => c = -12
a = -12,b = 6 => c = -12
a = -11,b = 6 => c = -6
a = -10,b = 6 => c = -6
a = -9,b = 6 => c = -6
a = -8,b = 6 => c = -6
a = 0,b = 6 => c = 0
a = 1,b = 6 => c = 0
a = 2,b = 6 => c = 0
a = 3,b = 6 => c = 0
a = 4,b = 6 => c = 0
a = 5,b = 6 => c = 0
a = 6,b = 6 => c = 6
a = 7,b = 6 => c = 6
a = 8,b = 6 => c = 6
a = 9,b = 6 => c = 6
---------------------------------
a = -18,b = 7 => c = -14
a = -17,b = 7 => c = -14
a = -16,b = 7 => c = -14
a = -15,b = 7 => c = -14
a = -14,b = 7 => c = -14
a = -13,b = 7 => c = -7
a = -12,b = 7 => c = -7
a = -11,b = 7 => c = -7
a = -10,b = 7 => c = -7
a = -9,b = 7 => c = -7
a = 0,b = 7 => c = 0
a = 1,b = 7 => c = 0
a = 2,b = 7 => c = 0
a = 3,b = 7 => c = 0
a = 4,b = 7 => c = 0
a = 5,b = 7 => c = 0
a = 6,b = 7 => c = 0
a = 7,b = 7 => c = 7
a = 8,b = 7 => c = 7
a = 9,b = 7 => c = 7
---------------------------------
a = -19,b = 8 => c = -16
a = -18,b = 8 => c = -16
a = -17,b = 8 => c = -16
a = -16,b = 8 => c = -16
a = -15,b = 8 => c = -8
a = -14,b = 8 => c = -8
a = -13,b = 8 => c = -8
a = -12,b = 8 => c = -8
a = -11,b = 8 => c = -8
a = -10,b = 8 => c = -8
a = 0,b = 8 => c = 0
a = 1,b = 8 => c = 0
a = 2,b = 8 => c = 0
a = 3,b = 8 => c = 0
a = 4,b = 8 => c = 0
a = 5,b = 8 => c = 0
a = 6,b = 8 => c = 0
a = 7,b = 8 => c = 0
a = 8,b = 8 => c = 8
a = 9,b = 8 => c = 8
---------------------------------
a = -20,b = 9 => c = -18
a = -19,b = 9 => c = -18
a = -18,b = 9 => c = -18
a = -17,b = 9 => c = -9
a = -16,b = 9 => c = -9
a = -15,b = 9 => c = -9
a = -14,b = 9 => c = -9
a = -13,b = 9 => c = -9
a = -12,b = 9 => c = -9
a = -11,b = 9 => c = -9
a = 0,b = 9 => c = 0
a = 1,b = 9 => c = 0
a = 2,b = 9 => c = 0
a = 3,b = 9 => c = 0
a = 4,b = 9 => c = 0
a = 5,b = 9 => c = 0
a = 6,b = 9 => c = 0
a = 7,b = 9 => c = 0
a = 8,b = 9 => c = 0
a = 9,b = 9 => c = 9
---------------------------------

输出:

let myViewController = storyboard.instantiateViewControllerWithIdentifier("MyViewControllerID") as! MyCustomViewController

答案 2 :(得分:0)

您引用的代码的行为实际上是正确的。负整数除法的定义是,对于 m n 为正整数,以下情况属实:

- (m)/ n = - (m / n)

因此,我在这里假设您实际要问的是如何获得:

a = -1 => c = -2
a = -2 => c = -2
a = -3 => c = -4
a = -4 => c = -4
a = -5 => c = -6

在这种情况下,不要使用整数除法,这不是你想要的。你想要的是浮点分区的底线。幸运的是,有地板功能可以帮到你。试试这个:

int c = b * floor((double)a / (double)b);

它应该能给你你想要的东西。